Revise Windmill integration

This commit is contained in:
Tuan Dang
2023-07-28 01:30:28 +07:00
parent adb27bb729
commit a7ece1830e
7 changed files with 70 additions and 84 deletions
-2
View File
@@ -131,7 +131,6 @@ export const syncIntegrationsHelper = async ({
for await (const integration of integrations) { for await (const integration of integrations) {
// get workspace, environment (shared) secrets // get workspace, environment (shared) secrets
const secrets = await BotService.getSecrets({ const secrets = await BotService.getSecrets({
// issue here?
workspaceId: integration.workspace, workspaceId: integration.workspace,
environment: integration.environment, environment: integration.environment,
secretPath: integration.secretPath, secretPath: integration.secretPath,
@@ -144,7 +143,6 @@ export const syncIntegrationsHelper = async ({
secretPath: integration.secretPath, secretPath: integration.secretPath,
}) })
const integrationAuth = await IntegrationAuth.findById( const integrationAuth = await IntegrationAuth.findById(
integration.integrationAuth integration.integrationAuth
); );
+2 -3
View File
@@ -766,7 +766,6 @@ const getAppsCodefresh = async ({
}; };
/** /**
* Return list of projects for Windmill integration * Return list of projects for Windmill integration
* @param {Object} obj * @param {Object} obj
@@ -784,8 +783,8 @@ const getAppsWindmill = async ({ accessToken }: { accessToken: string }) => {
}, },
} }
); );
//check for write access of secrets in windmill workspaces // check for write access of secrets in windmill workspaces
const writeAccessCheck = data.map(async (app: any) => { const writeAccessCheck = data.map(async (app: any) => {
try { try {
const userPath = "u/user/variable"; const userPath = "u/user/variable";
+63 -74
View File
@@ -48,6 +48,7 @@ import {
INTEGRATION_WINDMILL_API_URL, INTEGRATION_WINDMILL_API_URL,
} from "../variables"; } from "../variables";
import { standardRequest } from "../config/request"; import { standardRequest } from "../config/request";
import { handleAuthProviderCallback } from "../controllers/v1/authController";
/** /**
* Sync/push [secrets] to [app] in integration named [integration] * Sync/push [secrets] to [app] in integration named [integration]
@@ -2048,7 +2049,7 @@ const syncSecretsWindmill = async ({
} }
// get secrets stored in windmill workspace // get secrets stored in windmill workspace
const { data: getSecretsRes } = await standardRequest.get( const res = (await standardRequest.get(
`${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/list`, `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/list`,
{ {
headers: { headers: {
@@ -2056,87 +2057,75 @@ const syncSecretsWindmill = async ({
"Accept-Encoding": "application/json", "Accept-Encoding": "application/json",
}, },
} }
))
.data
.reduce(
(obj: any, secret: WindmillSecret) => ({
...obj,
[secret.path]: secret
}),
{}
); );
// convert secret results to [key] format
const secretsResList = getSecretsRes.map((secretObj: any) => (secretObj.path));
// convert the secrets to [{}] format
const modifiedFormatForCreateSecretInjection: WindmillSecret[] = [];
const modifiedFormatForUpdateSecretInjection: WindmillSecret[] = [];
Object.keys(secrets).forEach( const pattern = /^(u\/|f\/)[a-zA-Z0-9_-]+\/([a-zA-Z0-9_-]+\/)*[a-zA-Z0-9_-]*[^\/]$/;
(key) => {
const pattern = new RegExp('^[uf]+[\/](?:[a-zA-Z0-9-_]+[\/])*([a-zA-Z0-9-_]+)') for await (const key of Object.keys(secrets)) {
if((key.startsWith("u/") || key.startsWith("f/")) && pattern.test(key)) { if((key.startsWith("u/") || key.startsWith("f/")) && pattern.test(key)) {
if(secretsResList.includes(key)) { if(!(key in res)) {
modifiedFormatForUpdateSecretInjection.push({ // case: secret does not exist in windmill
path: key, // -> create secret
value: secrets[key],
is_secret: true, await standardRequest.post(
description: secretComments[key] || "" `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/create`,
}); {
path: key,
value: secrets[key],
is_secret: true,
description: secretComments[key] || ""
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Accept-Encoding": "application/json",
},
}
);
} else { } else {
modifiedFormatForCreateSecretInjection.push({ // -> update secret
path: key, await standardRequest.post(
value: secrets[key], `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/update/${res[key].path}`,
is_secret: true, {
description: secretComments[key] || "" path: key,
}); value: secrets[key],
is_secret: true,
description: secretComments[key] || ""
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Accept-Encoding": "application/json",
},
}
);
} }
}; };
} }
);
for await (const key of Object.keys(res)) {
// create new secrets in windmill workspace if (!(key in secrets)) {
modifiedFormatForCreateSecretInjection.forEach(async (secretObj: any) => { // -> delete secret
await standardRequest.post( await standardRequest.delete(
`${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/create`, `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/delete/${res[key].path}`,
secretObj, {
{ headers: {
headers: {
Authorization: `Bearer ${accessToken}`, Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"Accept-Encoding": "application/json", "Accept-Encoding": "application/json",
}, }
}
);
})
// update old secrets already present in windmill workspace
modifiedFormatForUpdateSecretInjection.forEach(async (secretObj: any) => {
await standardRequest.post(
`${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/update/${secretObj.path}`,
secretObj,
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Accept-Encoding": "application/json",
},
}
)
})
// create list of secrets to delete
const secretsToDelete: string[] = [];
secretsResList.forEach((secret: string) => {
if(!(secret in secrets)) {
secretsToDelete.push(secret);
}
})
// delete all secrets from secretsToDelete List
secretsToDelete.forEach(async (secret: string) => {
await standardRequest.delete(
`${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/delete/${secret}`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"Accept-Encoding": "application/json",
} }
} );
); }
}); }
}; };
export { syncSecrets }; export { syncSecrets };
+2 -2
View File
@@ -110,12 +110,12 @@ class BotService {
} }
/** /**
* Return decreypted secrets comment for workspace with id [worskpaceId] and * Return decrypted secret comments for workspace with id [worskpaceId] and
* environment [environment] shared to bot. * environment [environment] shared to bot.
* @param {Object} obj * @param {Object} obj
* @param {String} obj.workspaceId - id of workspace of secrets * @param {String} obj.workspaceId - id of workspace of secrets
* @param {String} obj.environment - environment for secrets * @param {String} obj.environment - environment for secrets
* @returns {Object} secretObj - object where keys are secret keys and values are comment values * @returns {Object} secretObj - object where keys are secret keys and values are comments
*/ */
static async getSecretComments({ static async getSecretComments({
workspaceId, workspaceId,
+1 -1
View File
@@ -22,7 +22,7 @@ const integrationSlugNameMapping: Mapping = {
'hashicorp-vault': 'Vault', 'hashicorp-vault': 'Vault',
'cloudflare-pages': 'Cloudflare Pages', 'cloudflare-pages': 'Cloudflare Pages',
'codefresh': 'Codefresh', 'codefresh': 'Codefresh',
'windmill': 'windmill' 'windmill': 'Windmill'
} }
const envMapping: Mapping = { const envMapping: Mapping = {
@@ -43,7 +43,7 @@ export default function WindmillCreateIntegrationPage() {
<Card className="max-w-md rounded-md p-8"> <Card className="max-w-md rounded-md p-8">
<CardTitle className="text-center">Windmill Integration</CardTitle> <CardTitle className="text-center">Windmill Integration</CardTitle>
<FormControl <FormControl
label="Windmill API Token" label="Windmill Access Token"
errorText={apiKeyErrorText} errorText={apiKeyErrorText}
isError={apiKeyErrorText !== "" ?? false} isError={apiKeyErrorText !== "" ?? false}
> >
@@ -114,7 +114,7 @@ export default function WindmillCreateIntegrationPage() {
placeholder="Provide a path, default is /" placeholder="Provide a path, default is /"
/> />
</FormControl> </FormControl>
<FormControl label="Windmill Workspace (Write Access)" className="mt-4"> <FormControl label="Windmill Workspace" className="mt-4">
<Select <Select
value={targetApp} value={targetApp}
onValueChange={(val) => setTargetApp(val)} onValueChange={(val) => setTargetApp(val)}