From 8f6917d8b8e4a5670891e6a56eb0b845a54c4370 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:39:37 -0700 Subject: [PATCH] GitOps - Fixes push New group/config and strategy changes --- npm-shrinkwrap.json | 101 ++++++++-------------------- package.json | 4 +- src/routers/gitops.js | 2 +- src/services/config-strategy.js | 4 +- src/services/gitops/index.js | 4 ++ src/services/gitops/push-changed.js | 7 +- src/services/gitops/push-new.js | 31 +++++---- tests/gitops.test.js | 2 +- 8 files changed, 60 insertions(+), 95 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 9778912..486aa6d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -19,11 +19,11 @@ "graphql": "^16.9.0", "graphql-http": "^1.22.1", "graphql-tag": "^2.12.6", - "helmet": "^7.1.0", + "helmet": "^8.0.0", "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "mongodb": "^6.9.0", - "mongoose": "^8.6.4", + "mongoose": "^8.7.0", "pino": "^9.4.0", "pino-pretty": "^11.2.2", "swagger-ui-express": "^5.0.1", @@ -1366,9 +1366,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.7.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.3.tgz", - "integrity": "sha512-qXKfhXXqGTyBskvWEzJZPUxSslAiLaB6JGP1ic/XTH9ctGgzdgYguuLP1C601aRTSDNlLb0jbKqXjZ48GNraSA==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -2551,9 +2551,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2567,9 +2567,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2579,14 +2579,14 @@ } }, "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "dev": true, "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3291,11 +3291,11 @@ } }, "node_modules/helmet": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", - "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.0.0.tgz", + "integrity": "sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/help-me": { @@ -4723,13 +4723,13 @@ } }, "node_modules/mongoose": { - "version": "8.6.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.4.tgz", - "integrity": "sha512-trOj6bHS3egVlKlCbQRsnMokaHFDRyQOvwA5wfl/pJx4j4EO5BAESavLf93NOTMpuo4T90/+V8CBk+sH3Ltr3g==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.0.tgz", + "integrity": "sha512-rUCSF1mMYQXjXYdqEQLLlMD3xbcj2j1/hRn+9VnVj7ipzru/UoUZxlj/hWmteKMAh4EFnDZ+BIrmma9l/0Hi1g==", "dependencies": { "bson": "^6.7.0", "kareem": "2.6.3", - "mongodb": "6.8.0", + "mongodb": "6.9.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", @@ -4743,51 +4743,6 @@ "url": "https://opencollective.com/mongoose" } }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", - "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.7.0", - "mongodb-connection-string-url": "^3.0.0" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -6303,9 +6258,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -6322,8 +6277,8 @@ } ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/package.json b/package.json index 5e7c70a..14732bc 100644 --- a/package.json +++ b/package.json @@ -46,11 +46,11 @@ "graphql": "^16.9.0", "graphql-http": "^1.22.1", "graphql-tag": "^2.12.6", - "helmet": "^7.1.0", + "helmet": "^8.0.0", "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "mongodb": "^6.9.0", - "mongoose": "^8.6.4", + "mongoose": "^8.7.0", "pino": "^9.4.0", "pino-pretty": "^11.2.2", "swagger-ui-express": "^5.0.1", diff --git a/src/routers/gitops.js b/src/routers/gitops.js index 86c2b05..3b62833 100644 --- a/src/routers/gitops.js +++ b/src/routers/gitops.js @@ -8,7 +8,7 @@ import * as Service from '../services/gitops/index.js'; const router = new express.Router(); -router.post('/gitops/v1/push', featureFlag, gitopsAuth, [ +router.post('/gitops/v1/push', gitopsAuth, featureFlag, [ body('environment').isString(), body('changes').isArray(), body('changes.*.path').isArray({ min: 0, max: 3 }), diff --git a/src/services/config-strategy.js b/src/services/config-strategy.js index 52c046a..7f7a94c 100644 --- a/src/services/config-strategy.js +++ b/src/services/config-strategy.js @@ -49,7 +49,7 @@ export async function populateAdmin(configStrategies) { } } -export async function createStrategy(args, admin) { +export async function createStrategy(args, admin, status = true) { const config = await getConfigById(args.config); if (!args.env) { @@ -61,7 +61,7 @@ export async function createStrategy(args, admin) { let configStrategy = new ConfigStrategy({ ...args, - activated: new Map().set(environment.name, true), + activated: new Map().set(environment.name, status), domain: config.domain, owner: admin._id }); diff --git a/src/services/gitops/index.js b/src/services/gitops/index.js index 07d3bab..134a72d 100644 --- a/src/services/gitops/index.js +++ b/src/services/gitops/index.js @@ -1,3 +1,4 @@ +import Logger from '../../helpers/logger.js'; import { getDomainById, updateDomainVersion } from '../domain.js'; import { processChanged } from './push-changed.js'; import { processDeleted } from './push-deleted.js'; @@ -6,6 +7,9 @@ import { processNew } from './push-new.js'; export const ADMIN_EMAIL = 'gitops@admin.noreply.switcherapi.com'; export async function pushChanges(domainId, environment, changes) { + Logger.debug(`Pushing changes to domain ${domainId} for environment ${environment}`); + Logger.debug(`Changes: ${JSON.stringify(changes)}`); + let domain = await getDomainById(domainId); for (const change of changes) { switch (change.action) { diff --git a/src/services/gitops/push-changed.js b/src/services/gitops/push-changed.js index 55b045e..bf9de3f 100644 --- a/src/services/gitops/push-changed.js +++ b/src/services/gitops/push-changed.js @@ -19,11 +19,12 @@ export async function processChanged(domain, change, environment) { async function processChangedGroup(domain, change, environment) { const admin = { _id: domain.owner, email: ADMIN_EMAIL }; + const content = change.content; const group = await getGroupConfig({ domain: domain._id, name: change.path[0] }); await updateGroup(group._id, { - description: getChangedValue(change.content.description, group.description), - activated: new Map().set(environment, getChangedValue(change.content.activated, group.activated.get(environment))) + description: getChangedValue(content.description, group.description), + activated: new Map().set(environment, getChangedValue(content.activated, group.activated.get(environment))) }, admin); } @@ -48,7 +49,7 @@ async function processChangedStrategy(domain, change, environment) { const config = await getConfig({ domain: domain._id, group: group._id, key: path[1] }); const strategies = await getStrategies({ config: config._id }); - const strategy = strategies.find(strategy => strategy.strategy === path[2] && strategy.activated.get(environment)); + const strategy = strategies.find(strategy => strategy.strategy === path[2] && strategy.activated.has(environment)); await updateStrategy(strategy._id, { description: getChangedValue(content.description, group.description), diff --git a/src/services/gitops/push-new.js b/src/services/gitops/push-new.js index 2c82e6d..4481915 100644 --- a/src/services/gitops/push-new.js +++ b/src/services/gitops/push-new.js @@ -26,16 +26,17 @@ export async function processNew(domain, change, environment) { async function processNewGroup(domain, change, environment) { const admin = { _id: domain.owner }; + const content = change.content; const group = await createGroup({ domain: domain._id, - name: change.content.name, - description: change.content.description, - activated: new Map().set(environment, change.content.activated), + name: content.name, + description: getNewValue(content.description, ''), + activated: new Map().set(environment, getNewValue(content.activated, true)), owner: domain.owner }, admin); - if (change.content.configs?.length) { - for (const config of change.content.configs) { + if (content.config?.length) { + for (const config of content.config) { await processNewConfig(domain, { path: [group.name], content: config @@ -51,8 +52,8 @@ async function processNewConfig(domain, change, environment) { const group = await getGroupConfig({ domain: domain._id, name: path[0] }); let componentIds; - if (change.content.components?.length) { - const components = await getComponents({ domain: domain._id, name: { $in: change.content.components } }); + if (content.components?.length) { + const components = await getComponents({ domain: domain._id, name: { $in: content.components } }); componentIds = components.map(component => component._id); } @@ -60,14 +61,14 @@ async function processNewConfig(domain, change, environment) { domain: domain._id, group: group._id, key: content.key, - description: content.description, - activated: new Map().set(environment, content.activated), + description: getNewValue(content.description, ''), + activated: new Map().set(environment, getNewValue(content.activated, true)), owner: domain.owner, components: componentIds }, admin); - if (change.content.strategies?.length) { - for (const strategy of change.content.strategies) { + if (content.strategies?.length) { + for (const strategy of content.strategies) { await processNewStrategy(domain, { path: [group.name, config.key], content: strategy @@ -84,14 +85,14 @@ async function processNewStrategy(domain, change, environment) { await createStrategy({ env: environment, - description: content.description, + description: getNewValue(content.description, ''), strategy: content.strategy, values: content.values, operation: content.operation, config: config._id, domain: domain._id, owner: domain.owner - }, admin); + }, admin, getNewValue(content.activated, true)); } async function processNewStrategyValue(domain, change) { @@ -122,4 +123,8 @@ async function processNewComponent(domain, change) { await addComponent(config._id, { component: id }, admin); } } +} + +function getNewValue(newValue, defaultValue) { + return newValue !== undefined ? newValue : defaultValue; } \ No newline at end of file diff --git a/tests/gitops.test.js b/tests/gitops.test.js index 35c05b8..7bdd2d2 100644 --- a/tests/gitops.test.js +++ b/tests/gitops.test.js @@ -136,7 +136,7 @@ describe('GitOps - Push New', () => { name: 'New Group and Switcher', description: 'New Group Description', activated: true, - configs: [{ + config: [{ key: 'NEW_SWITCHER_FROM_GROUP', description: 'New Switcher', activated: false,