@hiiretail/gcp-infra-generators 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/generators/clan-resources/clan-project/index.js +89 -189
  2. package/dist/generators/common-resources/bigquery/index.js +172 -267
  3. package/dist/generators/common-resources/budget/index.js +67 -153
  4. package/dist/generators/common-resources/cloud-armor/index.js +17 -167
  5. package/dist/generators/common-resources/cloud-storage/index.js +96 -205
  6. package/dist/generators/common-resources/cloudsql/index.js +71 -177
  7. package/dist/generators/common-resources/cloudsql-database/index.js +40 -287
  8. package/dist/generators/common-resources/confluent-cluster/index.js +23 -132
  9. package/dist/generators/common-resources/datastore/index.js +48 -194
  10. package/dist/generators/common-resources/elastic-cloud/index.js +22 -132
  11. package/dist/generators/common-resources/elastic-index-policy/handle-yaml.js +76 -0
  12. package/dist/generators/common-resources/elastic-index-policy/index.js +131 -286
  13. package/dist/generators/common-resources/elastic-template/index.js +52 -162
  14. package/dist/generators/common-resources/firestore/index.js +93 -233
  15. package/dist/generators/common-resources/iam/index.js +35 -157
  16. package/dist/generators/common-resources/iam/valid-prefix.js +8 -0
  17. package/dist/generators/common-resources/kafka-connect/index.js +35 -144
  18. package/dist/generators/common-resources/kafka-topics/index.js +20 -129
  19. package/dist/generators/common-resources/kms/index.js +31 -141
  20. package/dist/generators/common-resources/memorystore/index.js +42 -328
  21. package/dist/generators/common-resources/monitoring/handle-yaml.js +49 -0
  22. package/dist/generators/common-resources/monitoring/index.js +144 -322
  23. package/dist/generators/common-resources/monitoring/validate.js +58 -0
  24. package/dist/generators/common-resources/pubsub/append.js +130 -0
  25. package/dist/generators/common-resources/pubsub/get-gcp-projects.js +34 -0
  26. package/dist/generators/common-resources/pubsub/handle-subscribers.js +68 -0
  27. package/dist/generators/common-resources/pubsub/index.js +194 -536
  28. package/dist/generators/common-resources/pubsub/validate.js +53 -0
  29. package/dist/generators/common-resources/scheduler/append.js +85 -0
  30. package/dist/generators/common-resources/scheduler/index.js +62 -249
  31. package/dist/generators/common-resources/spanner/append.js +31 -0
  32. package/dist/generators/common-resources/spanner/index.js +102 -269
  33. package/dist/generators/common-resources/spanner/validate.js +38 -0
  34. package/dist/generators/docs/rca/index.js +25 -135
  35. package/dist/generators/docs/runbook/index.js +16 -126
  36. package/dist/generators/docs/srb/index.js +33 -147
  37. package/dist/generators/docs/srb/run-docker.js +2 -0
  38. package/dist/generators/init/clan-infra/gcp-projects.js +47 -0
  39. package/dist/generators/init/clan-infra/index.js +95 -290
  40. package/dist/generators/init/clan-infra/tribe-clan-repo.js +38 -0
  41. package/dist/generators/init/clan-infra/validate.js +8 -0
  42. package/dist/generators/maintenance/manage-states/index.js +142 -219
  43. package/dist/generators/maintenance/update-modules/index.js +56 -155
  44. package/dist/generators/organization/clan-project/googlecloud.js +124 -0
  45. package/dist/generators/organization/clan-project/index.js +81 -303
  46. package/dist/node_modules/.package-lock.json +81 -23
  47. package/dist/package.json +45 -0
  48. package/dist/src/BaseGenerator.js +84 -0
  49. package/dist/src/SecretsGenerator.js +137 -0
  50. package/dist/src/cli.js +54 -255
  51. package/dist/src/dependency-check.js +48 -0
  52. package/dist/src/update-check.js +38 -0
  53. package/dist/src/validators.js +33 -0
  54. package/dist/src/yeoman.js +80 -0
  55. package/package.json +1 -2
@@ -0,0 +1,84 @@
1
+ const Generator = require('yeoman-generator');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const inquirer = require('inquirer');
5
+ const { chain, required, filename } = require('./validators');
6
+
7
+ module.exports = class extends Generator {
8
+ constructor(args, opts) {
9
+ super(args, opts);
10
+
11
+ this.baseDir = path.resolve(path.join(__dirname, '..'));
12
+ this.destinationRoot(process.cwd());
13
+
14
+ const [command, generator] = opts.namespace.split(':').slice(-2);
15
+ this.generatorId = path.join(command, generator);
16
+ this.sourceRoot(
17
+ path.join(this.baseDir, 'generators', this.generatorId, 'templates'),
18
+ );
19
+
20
+ this.copyDir = (
21
+ templateDir,
22
+ targetDir,
23
+ answers = this.answers,
24
+ skipIfExists = false,
25
+ ) => {
26
+ if (skipIfExists && fs.existsSync(targetDir)) {
27
+ return;
28
+ }
29
+ this.fs.copyTpl(
30
+ this.templatePath(`${templateDir}/**/*`),
31
+ this.destinationPath(targetDir),
32
+ answers,
33
+ );
34
+ };
35
+
36
+ this.listSubDirectories = (parent) =>
37
+ fs
38
+ .readdirSync(parent)
39
+ .filter((f) => !f.startsWith('.'))
40
+ .filter((f) => fs.lstatSync(path.join(parent, f)).isDirectory())
41
+ .sort((a, b) => a.localeCompare(b));
42
+
43
+ this.kebabCase = (input) => input.replace(/\s|_/g, '-');
44
+
45
+ this.chooseOrCreatePrompts = (name, getChoicesDirectory) => [
46
+ {
47
+ when: (answers) => fs.existsSync(getChoicesDirectory(answers)),
48
+ type: 'list',
49
+ name,
50
+ message: `Choose ${name}`,
51
+ store: true,
52
+ choices: (answers) => [
53
+ ...this.listSubDirectories(getChoicesDirectory(answers)),
54
+ new inquirer.Separator(),
55
+ `Create new ${name}`,
56
+ ],
57
+ validate: required,
58
+ filter: this.kebabCase,
59
+ },
60
+ {
61
+ when: (answers) =>
62
+ !fs.existsSync(getChoicesDirectory(answers)) ||
63
+ answers[name] === `Create-new-${name}`,
64
+ type: 'input',
65
+ name: `new-${name}`,
66
+ message: `New ${name} name`,
67
+ store: false,
68
+ validate: (input) => chain(input, required, filename),
69
+ filter: this.kebabCase,
70
+ },
71
+ {
72
+ when: (answers) =>
73
+ !fs.existsSync(getChoicesDirectory(answers)) ||
74
+ answers[name] === 'Create-new-tribe',
75
+ type: 'input',
76
+ name: 'costCenter',
77
+ message: 'Please provide the Cost Center of the Tribe',
78
+ store: false,
79
+ validate: (input) => chain(input, required, filename),
80
+ filter: this.kebabCase,
81
+ },
82
+ ];
83
+ }
84
+ };
@@ -0,0 +1,137 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const printf = require('sprintf-js').sprintf;
4
+ const chalk = require('chalk');
5
+ const BaseGenerator = require('./BaseGenerator');
6
+
7
+ function getMaxStrLength(strings) {
8
+ let maxLength = 0;
9
+ Object.values(strings).forEach((string) => {
10
+ if (string.length > maxLength) {
11
+ maxLength = string.length;
12
+ }
13
+ });
14
+ return maxLength;
15
+ }
16
+
17
+ module.exports = class extends BaseGenerator {
18
+ writeSecrets(resource, instanceResource, instanceType, resourceName) {
19
+ ['prod', 'staging'].forEach((env) => {
20
+ this.init(env, resource, instanceResource, instanceType, resourceName);
21
+
22
+ if (fs.existsSync(path.resolve(this.secretsDir, 'terragrunt.hcl'))) {
23
+ fs.unlinkSync(path.join(this.secretsDir, 'terragrunt.hcl'));
24
+ } else {
25
+ fs.mkdirSync(this.secretsDir, { recursive: true });
26
+ }
27
+ this.createTemplate();
28
+ });
29
+ }
30
+
31
+ init(env, resource, instanceResource, instanceType, resourceName) {
32
+ this.resourceName = resourceName;
33
+ this.instanceType = instanceType;
34
+ this.resource = resource;
35
+ this.outputs = JSON.parse(
36
+ fs.readFileSync(
37
+ path.join(
38
+ this.baseDir,
39
+ 'generators',
40
+ this.generatorId,
41
+ 'templates',
42
+ this.instanceType,
43
+ 'outputs.json',
44
+ ),
45
+ 'utf8',
46
+ ),
47
+ );
48
+ this.secretsDir = path.join(
49
+ 'infra',
50
+ env,
51
+ resource,
52
+ instanceType,
53
+ instanceResource,
54
+ 'secrets',
55
+ );
56
+ if (fs.existsSync(path.join(this.secretsDir, 'state.json'))) {
57
+ this.stateNames = JSON.parse(
58
+ fs.readFileSync(path.join(this.secretsDir, 'state.json'), 'utf8'),
59
+ );
60
+ this.checkUniqueState();
61
+ this.stateNames.secrets.push(this.resourceName);
62
+ } else {
63
+ this.stateNames = { secrets: [this.resourceName] };
64
+ }
65
+ this.outputLen = getMaxStrLength(this.outputs);
66
+ this.stateLen = getMaxStrLength(this.stateNames.secrets);
67
+ }
68
+
69
+ checkUniqueState() {
70
+ this.stateNames.secrets.forEach((state) => {
71
+ if (state === this.resourceName) {
72
+ process.stderr.write(
73
+ `${chalk.red('ERROR!')} resource already exists\n`,
74
+ );
75
+ process.exit(1);
76
+ }
77
+ });
78
+ }
79
+
80
+ buildDependencies() {
81
+ const dependencies = [];
82
+ this.stateNames.secrets.forEach((secret) => {
83
+ let fp = `dependency "${secret}" {\n config_path = "../${secret}"\n mock_outputs = {\n`;
84
+ Object.values(this.outputs).forEach((value) => {
85
+ fp += printf(
86
+ `%-4s%-${this.outputLen}s %s`,
87
+ '',
88
+ `${value}`,
89
+ `= "dummy-${value}"\n`,
90
+ );
91
+ });
92
+ fp += ' }\n}\n';
93
+ dependencies.push(fp);
94
+ });
95
+ return dependencies;
96
+ }
97
+
98
+ buildSecrets() {
99
+ const secrets = [];
100
+ const resourceType =
101
+ this.instanceType === '' ? this.resource : this.instanceType;
102
+ const padding = resourceType.length + this.outputLen + this.stateLen + 2;
103
+ this.stateNames.secrets.forEach((secret) => {
104
+ const secretsSet = [];
105
+ Object.values(this.outputs).forEach((value) => {
106
+ secretsSet.push(
107
+ printf(
108
+ `\n%-6s%-${padding}s %s`,
109
+ '',
110
+ `${resourceType}_${secret}_${value}`,
111
+ `= dependency.${secret}.outputs.${value}`,
112
+ ),
113
+ );
114
+ });
115
+ secrets.push(secretsSet.join(''));
116
+ });
117
+ return secrets.join('');
118
+ }
119
+
120
+ updateState() {
121
+ fs.writeFileSync(
122
+ path.join(this.secretsDir, 'state.json'),
123
+ JSON.stringify(this.stateNames, null, 2),
124
+ );
125
+ }
126
+
127
+ createTemplate() {
128
+ const dependencies = this.buildDependencies().join('');
129
+ const secrets = this.buildSecrets();
130
+ this.updateState();
131
+ this.copyDir(path.join(this.instanceType, 'secrets'), this.secretsDir, {
132
+ ...this.answers,
133
+ dependencies,
134
+ secrets,
135
+ });
136
+ }
137
+ };
package/dist/src/cli.js CHANGED
@@ -1,283 +1,82 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
- var __commonJS = (cb, mod) => function __require() {
5
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
6
- };
7
-
8
- // package.json
9
- var require_package = __commonJS({
10
- "package.json"(exports2, module2) {
11
- module2.exports = {
12
- name: "@hiiretail/gcp-infra-generators",
13
- version: "1.0.0",
14
- description: "Infrastructure as code generator for GCP.",
15
- scripts: {
16
- build: "node esbuild.js && npm run build:deps",
17
- "build:deps": " npm prune --omit=dev --silent && cp -R ../../node_modules dist"
18
- },
19
- files: [
20
- "dist"
21
- ],
22
- repository: "github:extenda/gcp-infra-cli",
23
- readme: "https://github.com/extenda/gcp-infra-cli/tree/master/packages/generators#readme",
24
- author: {
25
- name: "Extenda Retail",
26
- email: "info@extendaretail.com",
27
- url: "https://extendaretail.com"
28
- },
29
- license: "MIT",
30
- keywords: [
31
- "terraform",
32
- "terragrunt",
33
- "cli"
34
- ],
35
- dependencies: {
36
- "@google-cloud/storage": "^7.16.0",
37
- axios: "^1.11.0",
38
- chalk: "^4.1.2",
39
- commander: "^14.0.0",
40
- ejs: "^3.1.10",
41
- "enquirer-separator": "^0.1.0",
42
- glob: "^11.0.3",
43
- inquirer: "^7.3.3",
44
- "js-yaml": "^4.1.0",
45
- semver: "^7.3.2",
46
- "sprintf-js": "^1.1.3",
47
- "yeoman-environment": "^2.10.3",
48
- "yeoman-generator": "^4.13.0"
49
- },
50
- devDependencies: {
51
- esbuild: "^0.25.8",
52
- "mock-fs": "^5.5.0",
53
- "yeoman-assert": "^3.1.1",
54
- "yeoman-test": "^2.7.0"
55
- }
56
- };
57
- }
58
- });
59
-
60
- // src/yeoman.js
61
- var require_yeoman = __commonJS({
62
- "src/yeoman.js"(exports2, module2) {
63
- var fs2 = require("fs");
64
- var path2 = require("path");
65
- var inquirer = require("inquirer");
66
- var yeoman = require("yeoman-environment");
67
- var env;
68
- var lookupGenerators = /* @__PURE__ */ __name((dir) => {
69
- const opts = {
70
- packagePaths: dir,
71
- localOnly: true,
72
- filePatterns: "*/index.js"
73
- };
74
- const generators = [];
75
- env.lookup(opts, () => {
76
- Object.values(env.getGeneratorsMeta()).forEach(
77
- ({ resolved, namespace }) => {
78
- env.register(resolved, namespace);
79
- const generatorJson = path2.join(
80
- path2.dirname(resolved),
81
- "generator.json"
82
- );
83
- const name = JSON.parse(fs2.readFileSync(generatorJson, "utf8")).name || namespace;
84
- generators.push({
85
- name,
86
- value: namespace
87
- });
88
- }
89
- );
90
- });
91
- return generators;
92
- }, "lookupGenerators");
93
- var runYeoman2 = /* @__PURE__ */ __name(async (dir, name, query) => {
94
- if (!env) {
95
- env = yeoman.createEnv();
96
- }
97
- const generators = lookupGenerators(dir);
98
- if (generators.length === 1) {
99
- return env.run(generators[0].value);
100
- }
101
- if (name) {
102
- const match = generators.find((g) => g.value.endsWith(`:${name}`));
103
- if (match) {
104
- return env.run(match.value);
105
- }
106
- }
107
- return env.adapter.prompt([
108
- {
109
- type: "list",
110
- name: "generator",
111
- message: query,
112
- choices: [...generators, new inquirer.Separator(), "Exit"],
113
- store: false
114
- }
115
- ]).then(({ generator }) => {
116
- if (generator !== "Exit") {
117
- return env.run(generator);
118
- }
119
- return null;
120
- });
121
- }, "runYeoman");
122
- var setEnvironment = /* @__PURE__ */ __name((yeomanEnv) => {
123
- env = yeomanEnv;
124
- }, "setEnvironment");
125
- module2.exports = {
126
- runYeoman: runYeoman2,
127
- setEnvironment
128
- };
129
- }
130
- });
131
-
132
- // src/dependency-check.js
133
- var require_dependency_check = __commonJS({
134
- "src/dependency-check.js"(exports2, module2) {
135
- var path2 = require("path");
136
- var fs2 = require("fs");
137
- var chalk = require("chalk");
138
- var printAndExit = /* @__PURE__ */ __name((message) => {
139
- process.stderr.write(`${chalk.red("ERROR!")} ${message}
140
- `);
141
- process.exit(1);
142
- }, "printAndExit");
143
- var checkInit = /* @__PURE__ */ __name(() => {
144
- if (!fs2.existsSync(path2.join("infra", "common.hcl"))) {
145
- printAndExit("Run init before resources");
146
- }
147
- }, "checkInit");
148
- var checkGitRepo = /* @__PURE__ */ __name(() => {
149
- if (!fs2.existsSync(path2.join(".git"))) {
150
- printAndExit("Run this command in the root of your Git repository");
151
- }
152
- }, "checkGitRepo");
153
- var checkOrgRepo = /* @__PURE__ */ __name(() => {
154
- if (!fs2.existsSync(path2.join("organization"))) {
155
- printAndExit("Run this command in your organizations infra repository");
156
- }
157
- }, "checkOrgRepo");
158
- var requireCheck = /* @__PURE__ */ __name((dependencies) => {
159
- dependencies.forEach((dependency) => {
160
- switch (dependency) {
161
- case "init":
162
- checkInit();
163
- break;
164
- case "git-repo":
165
- checkGitRepo();
166
- break;
167
- case "org":
168
- checkOrgRepo();
169
- break;
170
- default:
171
- throw new Error(`Unsupported check: ${dependency}`);
172
- }
173
- });
174
- }, "requireCheck");
175
- module2.exports = {
176
- requireCheck
177
- };
178
- }
179
- });
180
-
181
- // src/update-check.js
182
- var require_update_check = __commonJS({
183
- "src/update-check.js"(exports2, module2) {
184
- var semver = require("semver");
185
- var chalk = require("chalk");
186
- var axios = require("axios");
187
- var { version: packageVersion2 } = require_package();
188
- var packageName = "@hiiretail/gcp-infra-cli";
189
- var getRegistryVersion = /* @__PURE__ */ __name(async () => {
190
- return axios.get(`https://registry.npmjs.org/${packageName}`).then((response) => {
191
- const {
192
- data: {
193
- "dist-tags": { latest }
194
- }
195
- } = response;
196
- return latest;
197
- });
198
- }, "getRegistryVersion");
199
- var isUpdateRequired2 = /* @__PURE__ */ __name(async (version = packageVersion2) => {
200
- const registryVersion = await getRegistryVersion();
201
- return semver.lt(version, registryVersion) && version !== "0.0.1-local";
202
- }, "isUpdateRequired");
203
- var printUpdateMessage2 = /* @__PURE__ */ __name(async () => {
204
- const newVersion = await getRegistryVersion();
205
- process.stdout.write(`${chalk.yellow("SOFTWARE UPDATE!")} Version ${newVersion} has been released.
206
- Please run the following command to upgrade to the latest version:
207
-
208
- ${chalk.green(`npm install --global ${packageName}@latest`)}
209
- `);
210
- }, "printUpdateMessage");
211
- module2.exports = {
212
- isUpdateRequired: isUpdateRequired2,
213
- printUpdateMessage: printUpdateMessage2
214
- };
215
- }
216
- });
217
-
218
- // src/cli.js
219
- var path = require("path");
220
- var fs = require("fs");
221
- var glob = require("glob");
222
- var { Command } = require("commander");
223
- var {
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const glob = require('glob');
4
+ const { Command } = require('commander');
5
+ const {
224
6
  version: packageVersion,
225
- description: packageDescription
226
- } = require_package();
227
- var { runYeoman } = require_yeoman();
228
- var dependencyCheck = require_dependency_check();
229
- var { isUpdateRequired, printUpdateMessage } = require_update_check();
230
- var addGenerators = /* @__PURE__ */ __name((commandDir, command, require2) => {
7
+ description: packageDescription,
8
+ } = require('../package.json');
9
+ const { runYeoman } = require('./yeoman');
10
+ const dependencyCheck = require('./dependency-check');
11
+ const { isUpdateRequired, printUpdateMessage } = require('./update-check');
12
+
13
+ const addGenerators = (commandDir, command, require) => {
231
14
  glob.sync(`${commandDir}/*/generator.json`).forEach((file) => {
232
15
  const dir = path.dirname(file);
233
- const info = JSON.parse(fs.readFileSync(file, "utf8"));
16
+ const info = JSON.parse(fs.readFileSync(file, 'utf8'));
234
17
  const name = path.basename(dir);
235
- command.command(name).description(info.description).action(() => {
236
- dependencyCheck.requireCheck(require2);
237
- return runYeoman(commandDir, name);
238
- });
18
+ command
19
+ .command(name)
20
+ .description(info.description)
21
+ .action(() => {
22
+ dependencyCheck.requireCheck(require);
23
+ return runYeoman(commandDir, name);
24
+ });
239
25
  });
240
- }, "addGenerators");
241
- var createCommands = /* @__PURE__ */ __name((program) => {
26
+ };
27
+
28
+ const createCommands = (program) => {
242
29
  const opts = {
243
- cwd: path.resolve(__dirname, ".."),
244
- absolute: true
30
+ cwd: path.resolve(__dirname, '..'),
31
+ absolute: true,
245
32
  };
246
- glob.sync("generators/*/command.json", opts).forEach((file) => {
33
+ glob.sync('generators/*/command.json', opts).forEach((file) => {
247
34
  const dir = path.dirname(file);
248
35
  const name = path.basename(dir);
249
36
  const {
250
- query = "Choose a generator",
251
- description = "",
252
- require: require2 = []
253
- } = JSON.parse(fs.readFileSync(path.join(file), "utf8"));
254
- const command = program.command(name).description(description).action(() => {
255
- dependencyCheck.requireCheck(require2);
256
- return runYeoman(dir, "", query);
257
- });
258
- addGenerators(dir, command, require2);
37
+ query = 'Choose a generator',
38
+ description = '',
39
+ require = [],
40
+ } = JSON.parse(fs.readFileSync(path.join(file), 'utf8'));
41
+ const command = program
42
+ .command(name)
43
+ .description(description)
44
+ .action(() => {
45
+ dependencyCheck.requireCheck(require);
46
+ return runYeoman(dir, '', query);
47
+ });
48
+ addGenerators(dir, command, require);
259
49
  });
260
50
  return program;
261
- }, "createCommands");
262
- var cli = /* @__PURE__ */ __name(async (argv, exitOverride, cliVersion = "0.0.1-local") => {
51
+ };
52
+
53
+ const cli = async (argv, exitOverride, cliVersion = '0.0.1-local') => {
263
54
  const needsUpdate = await isUpdateRequired(cliVersion);
264
55
  if (needsUpdate) {
265
56
  await printUpdateMessage();
266
57
  process.exit(1);
267
58
  }
59
+
268
60
  const command = new Command();
269
61
  if (exitOverride) {
270
62
  command.exitOverride(exitOverride);
271
63
  }
272
- return createCommands(command).version(
273
- `gcp-infra ${cliVersion}
64
+
65
+ return createCommands(command)
66
+ .version(
67
+ `gcp-infra ${cliVersion}
274
68
  gcp-infra-generators ${packageVersion}
275
- `
276
- ).description(packageDescription).addHelpCommand(false).parseAsync(argv);
277
- }, "cli");
69
+ `,
70
+ )
71
+ .description(packageDescription)
72
+ .addHelpCommand(false)
73
+ .parseAsync(argv);
74
+ };
75
+
278
76
  if (require.main === module) {
279
77
  cli().then(() => {
280
78
  process.exit(0);
281
79
  });
282
80
  }
81
+
283
82
  module.exports = cli;
@@ -0,0 +1,48 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const chalk = require('chalk');
4
+
5
+ const printAndExit = (message) => {
6
+ process.stderr.write(`${chalk.red('ERROR!')} ${message}\n`);
7
+ process.exit(1);
8
+ };
9
+
10
+ const checkInit = () => {
11
+ if (!fs.existsSync(path.join('infra', 'common.hcl'))) {
12
+ printAndExit('Run init before resources');
13
+ }
14
+ };
15
+
16
+ const checkGitRepo = () => {
17
+ if (!fs.existsSync(path.join('.git'))) {
18
+ printAndExit('Run this command in the root of your Git repository');
19
+ }
20
+ };
21
+
22
+ const checkOrgRepo = () => {
23
+ if (!fs.existsSync(path.join('organization'))) {
24
+ printAndExit('Run this command in your organizations infra repository');
25
+ }
26
+ };
27
+
28
+ const requireCheck = (dependencies) => {
29
+ dependencies.forEach((dependency) => {
30
+ switch (dependency) {
31
+ case 'init':
32
+ checkInit();
33
+ break;
34
+ case 'git-repo':
35
+ checkGitRepo();
36
+ break;
37
+ case 'org':
38
+ checkOrgRepo();
39
+ break;
40
+ default:
41
+ throw new Error(`Unsupported check: ${dependency}`);
42
+ }
43
+ });
44
+ };
45
+
46
+ module.exports = {
47
+ requireCheck,
48
+ };
@@ -0,0 +1,38 @@
1
+ const semver = require('semver');
2
+ const chalk = require('chalk');
3
+ const axios = require('axios');
4
+ const { version: packageVersion } = require('../package.json');
5
+ const packageName = '@hiiretail/gcp-infra-cli';
6
+
7
+ const getRegistryVersion = async () => {
8
+ return axios
9
+ .get(`https://registry.npmjs.org/${packageName}`)
10
+ .then((response) => {
11
+ const {
12
+ data: {
13
+ 'dist-tags': { latest },
14
+ },
15
+ } = response;
16
+ return latest;
17
+ });
18
+ };
19
+
20
+ const isUpdateRequired = async (version = packageVersion) => {
21
+ const registryVersion = await getRegistryVersion();
22
+ return semver.lt(version, registryVersion) && version !== '0.0.1-local';
23
+ };
24
+
25
+ const printUpdateMessage = async () => {
26
+ const newVersion = await getRegistryVersion();
27
+ process.stdout
28
+ .write(`${chalk.yellow('SOFTWARE UPDATE!')} Version ${newVersion} has been released.
29
+ Please run the following command to upgrade to the latest version:
30
+
31
+ ${chalk.green(`npm install --global ${packageName}@latest`)}
32
+ `);
33
+ };
34
+
35
+ module.exports = {
36
+ isUpdateRequired,
37
+ printUpdateMessage,
38
+ };
@@ -0,0 +1,33 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ chain: (input, ...validators) => {
5
+ let msg = '';
6
+ validators.every((validator) => {
7
+ msg = validator(input);
8
+ return msg === true;
9
+ });
10
+ return msg === true ? true : msg;
11
+ },
12
+ filename: (input) => {
13
+ if (!input) {
14
+ // Optional input OK
15
+ return true;
16
+ }
17
+ return path.basename(input) === input ? true : 'Invalid filename';
18
+ },
19
+ maxLength: (input, maxLength) =>
20
+ !input || input.length <= maxLength
21
+ ? true
22
+ : `Exceeds max length: ${maxLength}`,
23
+ required: (input) => {
24
+ const msg = 'Required';
25
+ if (Array.isArray(input)) {
26
+ return input.length > 0 ? true : msg;
27
+ }
28
+ if (input) {
29
+ return input.trim().length > 0 ? true : msg;
30
+ }
31
+ return msg;
32
+ },
33
+ };