Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add workspace integrations command #284

Merged
merged 3 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format of this file is based on [Keep a Changelog](https://keepachangelog.co

## unreleased

### Added

- Added `workspaces integrations list` command (#284)

## [2.23.0] - 2024-03-01

### Changed
Expand Down
22 changes: 11 additions & 11 deletions src/integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use crate::output::{output_json, output_list};
use anyhow::Result;
use clap::{Parser, ValueEnum};
use cli_table::Table;
use fiberplane::api_client::integrations_get;
use fiberplane::models::integrations::IntegrationSummary;
use fiberplane::api_client::integrations_get_by_user;
use fiberplane::models::integrations::PersonalIntegrationSummary;
use std::path::PathBuf;
use time::format_description::well_known::Rfc3339;
use url::Url;
Expand Down Expand Up @@ -44,7 +44,7 @@ struct ListArgs {
}

#[derive(ValueEnum, Clone)]
enum IntegrationOutput {
pub(crate) enum IntegrationOutput {
/// Output the details of the integrations as a table
Table,

Expand All @@ -54,7 +54,7 @@ enum IntegrationOutput {

async fn handle_integrations_list(args: ListArgs) -> Result<()> {
let client = api_client_configuration(args.token, args.config, args.base_url).await?;
let integrations = integrations_get(&client).await?;
let integrations = integrations_get_by_user(&client).await?;

match args.output {
IntegrationOutput::Table => {
Expand All @@ -66,22 +66,22 @@ async fn handle_integrations_list(args: ListArgs) -> Result<()> {
}

#[derive(Table)]
struct IntegrationRow {
pub(crate) struct IntegrationRow {
#[table(title = "ID")]
id: String,
pub(crate) id: String,

#[table(title = "Status")]
status: String,
pub(crate) status: String,

#[table(title = "Created at")]
created_at: String,
pub(crate) created_at: String,

#[table(title = "Updated at")]
updated_at: String,
pub(crate) updated_at: String,
}

impl From<IntegrationSummary> for IntegrationRow {
fn from(integration: IntegrationSummary) -> Self {
impl From<PersonalIntegrationSummary> for IntegrationRow {
fn from(integration: PersonalIntegrationSummary) -> Self {
Self {
id: integration.id.to_string(),
status: integration.status.to_string(),
Expand Down
8 changes: 5 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ mod events;
mod experiments;
mod fp_urls;
mod front_matter;
mod integrations;
pub(crate) mod integrations;
mod interactive;
mod labels;
mod manifest;
Expand Down Expand Up @@ -226,9 +226,11 @@ enum SubCommand {
#[clap(aliases = &["webhook", "wh"])]
Webhooks(webhooks::Arguments),

/// Interact with integrations
/// Interact with personal integrations.
///
/// Integrations allow you to integrate various third-party tools into Fiberplane
/// Integrations allow you to integrate various third-party tools into Fiberplane.
///
/// If you wish to configure workspace level integrations, please use `fp workspaces integrations`
#[clap(alias = "integration")]
Integrations(integrations::Arguments),

Expand Down
74 changes: 71 additions & 3 deletions src/workspaces.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::config::api_client_configuration;
use crate::integrations::{IntegrationOutput, IntegrationRow};
use crate::interactive::{
data_source_picker, default_theme, name_opt, text_opt, text_req, workspace_picker,
workspace_user_picker,
Expand All @@ -9,12 +10,14 @@ use clap::{Parser, ValueEnum};
use cli_table::Table;
use dialoguer::FuzzySelect;
use fiberplane::api_client::{
workspace_create, workspace_delete, workspace_get, workspace_invite_create,
workspace_invite_delete, workspace_invite_get, workspace_leave, workspace_list,
workspace_update, workspace_user_list, workspace_user_remove, workspace_user_update,
integrations_get_by_workspace, workspace_create, workspace_delete, workspace_get,
workspace_invite_create, workspace_invite_delete, workspace_invite_get, workspace_leave,
workspace_list, workspace_update, workspace_user_list, workspace_user_remove,
workspace_user_update,
};
use fiberplane::base64uuid::Base64Uuid;
use fiberplane::models::data_sources::{ProviderType, SelectedDataSource};
use fiberplane::models::integrations::WorkspaceIntegrationSummary;
use fiberplane::models::names::Name;
use fiberplane::models::sorting::{
SortDirection, WorkspaceInviteListingSortFields, WorkspaceListingSortFields,
Expand All @@ -26,6 +29,7 @@ use fiberplane::models::workspaces::{
};
use std::collections::BTreeMap;
use std::{fmt::Display, path::PathBuf};
use time::format_description::well_known::Rfc3339;
use tracing::info;
use url::Url;

Expand Down Expand Up @@ -60,6 +64,10 @@ enum SubCommand {
/// List, update and remove users from a workspace
#[clap(subcommand)]
Users(UsersSubCommand),

/// List, update and remove integrations from a workspace
#[clap(subcommand)]
Integrations(IntegrationsSubCommand),
}

#[derive(Parser)]
Expand Down Expand Up @@ -89,6 +97,12 @@ enum UsersSubCommand {
Delete(UserDeleteArgs),
}

#[derive(Parser)]
enum IntegrationsSubCommand {
/// List the integrations that are connected to this workspace
List(ListIntegrationsArgs),
}

pub async fn handle_command(args: Arguments) -> Result<()> {
match args.sub_command {
SubCommand::Create(args) => handle_workspace_create(args).await,
Expand All @@ -112,6 +126,9 @@ pub async fn handle_command(args: Arguments) -> Result<()> {
handle_default_data_sources_command(sub_command).await
}
},
SubCommand::Integrations(sub_command) => match sub_command {
IntegrationsSubCommand::List(args) => handle_integrations_list(args).await,
},
}
}

Expand Down Expand Up @@ -669,6 +686,25 @@ pub(crate) struct UnsetDefaultDataSourcesArgs {
token: Option<String>,
}

#[derive(Parser)]
pub(crate) struct ListIntegrationsArgs {
/// Output of the webhooks
#[clap(long, short, default_value = "table", value_enum)]
output: IntegrationOutput,

#[clap(from_global)]
workspace_id: Option<Base64Uuid>,

#[clap(from_global)]
base_url: Url,

#[clap(from_global)]
config: Option<PathBuf>,

#[clap(from_global)]
token: Option<String>,
}

async fn handle_move_owner(args: MoveOwnerArgs) -> Result<()> {
let client = api_client_configuration(args.token, args.config, args.base_url).await?;
let workspace_id = workspace_picker(&client, args.workspace_id).await?;
Expand Down Expand Up @@ -801,6 +837,21 @@ async fn handle_unset_default_data_source(args: UnsetDefaultDataSourcesArgs) ->
Ok(())
}

async fn handle_integrations_list(args: ListIntegrationsArgs) -> Result<()> {
let client = api_client_configuration(args.token, args.config, args.base_url).await?;
let workspace_id = workspace_picker(&client, args.workspace_id).await?;

let integrations = integrations_get_by_workspace(&client, workspace_id).await?;

match args.output {
IntegrationOutput::Table => {
let rows: Vec<IntegrationRow> = integrations.into_iter().map(Into::into).collect();
output_list(rows)
}
IntegrationOutput::Json => output_json(&integrations),
}
}

#[derive(ValueEnum, Clone)]
enum WorkspaceOutput {
/// Output the details as a table
Expand Down Expand Up @@ -998,6 +1049,23 @@ impl From<Membership> for MembershipRow {
}
}

impl From<WorkspaceIntegrationSummary> for IntegrationRow {
fn from(integration: WorkspaceIntegrationSummary) -> Self {
Self {
id: integration.id.to_string(),
status: integration.status.to_string(),
created_at: integration.created_at.map_or_else(
|| "n/a".to_string(),
|time| time.format(&Rfc3339).unwrap_or_default(),
),
updated_at: integration.updated_at.map_or_else(
|| "n/a".to_string(),
|time| time.format(&Rfc3339).unwrap_or_default(),
),
}
}
}

fn print_data_sources(input: &BTreeMap<ProviderType, SelectedDataSource>) -> impl Display {
let mut output = String::new();
let mut iterator = input.iter().peekable();
Expand Down
Loading