From 03adbdb8a66d6f71f0579f908b7f94972a3ca262 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Thu, 22 Jun 2023 14:20:46 +0200 Subject: [PATCH] feat(cli): add skipSecrets, skipVariables, skipResources --- backend/windmill-api/src/workspaces.rs | 30 ++++++++++++++++++++------ cli/pull.ts | 12 ++++++++--- cli/sync.ts | 18 ++++++++++------ 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index f16f2b4c57..c4510b91a1 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -1194,6 +1194,10 @@ impl ArchiveImpl { struct ArchiveQueryParams { archive_type: Option, plain_secret: Option, + plain_secrets: Option, + skip_secrets: Option, + skip_variables: Option, + skip_resources: Option, } #[inline] @@ -1241,7 +1245,14 @@ async fn tarball_workspace( authed: Authed, Extension(db): Extension, Path(w_id): Path, - Query(ArchiveQueryParams { archive_type, plain_secret }): Query, + Query(ArchiveQueryParams { + archive_type, + plain_secret, + plain_secrets, + skip_resources, + skip_secrets, + skip_variables, + }): Query, ) -> Result<([(headers::HeaderName, String); 2], impl IntoResponse)> { require_admin(authed.is_admin, &authed.username)?; @@ -1317,7 +1328,7 @@ async fn tarball_workspace( } } - { + if !skip_resources.unwrap_or(false) { let resources = sqlx::query_as!( Resource, "SELECT * FROM resource WHERE workspace_id = $1", @@ -1334,7 +1345,7 @@ async fn tarball_workspace( } } - { + if !skip_resources.unwrap_or(false) { let resource_types = sqlx::query_as!( ResourceType, "SELECT * FROM resource_type WHERE workspace_id = $1", @@ -1370,9 +1381,13 @@ async fn tarball_workspace( } } - { + if !skip_variables.unwrap_or(false) { let variables = sqlx::query_as::<_, ExportableListableVariable>( - "SELECT *, false as is_expired FROM variable WHERE workspace_id = $1", + if !skip_secrets.unwrap_or(false) { + "SELECT *, false as is_expired FROM variable WHERE workspace_id = $1" + } else { + "SELECT *, false as is_expired FROM variable WHERE workspace_id = $1 AND is_secret = false" + } ) .bind(&w_id) .fetch_all(&db) @@ -1381,7 +1396,10 @@ async fn tarball_workspace( let mc = build_crypt(&mut db.begin().await?, &w_id).await?; for mut var in variables { - if plain_secret.unwrap_or(false) && var.value.is_some() && var.is_secret { + if plain_secret.or(plain_secrets).unwrap_or(false) + && var.value.is_some() + && var.is_secret + { var.value = Some( mc.decrypt_base64_to_string(var.value.unwrap()) .map_err(|e| Error::InternalErr(e.to_string()))?, diff --git a/cli/pull.ts b/cli/pull.ts index 587a252bab..1230bdd069 100644 --- a/cli/pull.ts +++ b/cli/pull.ts @@ -5,7 +5,10 @@ import { Workspace } from "./workspace.ts"; export async function downloadZip( workspace: Workspace, - plainSecrets: boolean | undefined + plainSecrets: boolean | undefined, + skipVariables?: boolean, + skipResources?: boolean, + skipSecrets?: boolean ): Promise { const requestHeaders: HeadersInit = new Headers(); requestHeaders.set("Authorization", "Bearer " + workspace.token); @@ -15,8 +18,11 @@ export async function downloadZip( workspace.remote + "api/w/" + workspace.workspaceId + - "/workspaces/tarball?archive_type=zip&plain_secret=" + - (plainSecrets ?? false), + `/workspaces/tarball?archive_type=zip&plain_secret=${ + plainSecrets ?? false + }&skip_variables=${skipVariables ?? false}&skip_resources=${ + skipResources ?? false + }&skip_secrets=${skipSecrets ?? false}`, { headers: requestHeaders, method: "GET", diff --git a/cli/sync.ts b/cli/sync.ts index 60c77e8bb3..32878fe29b 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -287,8 +287,7 @@ type Change = Added | Deleted | Edit; async function elementsToMap( els: DynFSElement, ignore: (path: string, isDirectory: boolean) => boolean, - json: boolean, - workspace: string + json: boolean ): Promise<{ [key: string]: string }> { const map: { [key: string]: string } = {}; for await (const entry of readDirRecursiveWithIgnore(ignore, els)) { @@ -311,15 +310,14 @@ async function compareDynFSElement( els1: DynFSElement, els2: DynFSElement | undefined, ignore: (path: string, isDirectory: boolean) => boolean, - json: boolean, - workspace: string + json: boolean ): Promise { const [m1, m2] = els2 ? await Promise.all([ - elementsToMap(els1, ignore, json, workspace), - elementsToMap(els2, ignore, json, workspace), + elementsToMap(els1, ignore, json), + elementsToMap(els2, ignore, json), ]) - : [await elementsToMap(els1, ignore, json, workspace), {}]; + : [await elementsToMap(els1, ignore, json), {}]; const changes: Change[] = []; @@ -393,6 +391,9 @@ async function pull( failConflicts: boolean; plainSecrets?: boolean; json?: boolean; + skipVariables?: boolean; + skipResources?: boolean; + skipSecrets?: boolean; } ) { if (!opts.raw) { @@ -592,6 +593,9 @@ async function push( failConflicts: boolean; plainSecrets?: boolean; json?: boolean; + skipVariables?: boolean; + skipResources?: boolean; + skipSecrets?: boolean; } ) { if (!opts.raw) {