@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
@@ -1,294 +1,213 @@
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
- // src/validators.js
9
- var require_validators = __commonJS({
10
- "src/validators.js"(exports2, module2) {
11
- var path2 = require("path");
12
- module2.exports = {
13
- chain: /* @__PURE__ */ __name((input, ...validators) => {
14
- let msg = "";
15
- validators.every((validator) => {
16
- msg = validator(input);
17
- return msg === true;
18
- });
19
- return msg === true ? true : msg;
20
- }, "chain"),
21
- filename: /* @__PURE__ */ __name((input) => {
22
- if (!input) {
23
- return true;
24
- }
25
- return path2.basename(input) === input ? true : "Invalid filename";
26
- }, "filename"),
27
- maxLength: /* @__PURE__ */ __name((input, maxLength) => !input || input.length <= maxLength ? true : `Exceeds max \
28
- length: ${maxLength}`, "maxLength"),
29
- required: /* @__PURE__ */ __name((input) => {
30
- const msg = "Required";
31
- if (Array.isArray(input)) {
32
- return input.length > 0 ? true : msg;
33
- }
34
- if (input) {
35
- return input.trim().length > 0 ? true : msg;
36
- }
37
- return msg;
38
- }, "required")
39
- };
40
- }
41
- });
42
-
43
- // src/BaseGenerator.js
44
- var require_BaseGenerator = __commonJS({
45
- "src/BaseGenerator.js"(exports2, module2) {
46
- var Generator = require("yeoman-generator");
47
- var path2 = require("path");
48
- var fs2 = require("fs");
49
- var inquirer2 = require("inquirer");
50
- var { chain, required, filename } = require_validators();
51
- module2.exports = class extends Generator {
52
- constructor(args, opts) {
53
- super(args, opts);
54
- this.baseDir = path2.resolve(path2.join(__dirname, ".."));
55
- this.destinationRoot(process.cwd());
56
- const [command, generator] = opts.namespace.split(":").slice(-2);
57
- this.generatorId = path2.join(command, generator);
58
- this.sourceRoot(
59
- path2.join(this.baseDir, "generators", this.generatorId, "templates")
60
- );
61
- this.copyDir = (templateDir, targetDir, answers = this.answers, skipIfExists = false) => {
62
- if (skipIfExists && fs2.existsSync(targetDir)) {
63
- return;
64
- }
65
- this.fs.copyTpl(
66
- this.templatePath(`${templateDir}/**/*`),
67
- this.destinationPath(targetDir),
68
- answers
69
- );
70
- };
71
- this.listSubDirectories = (parent) => fs2.readdirSync(parent).filter((f) => !f.startsWith(".")).filter((f) => fs2.
72
- lstatSync(path2.join(parent, f)).isDirectory()).sort((a, b) => a.localeCompare(b));
73
- this.kebabCase = (input) => input.replace(/\s|_/g, "-");
74
- this.chooseOrCreatePrompts = (name, getChoicesDirectory) => [
75
- {
76
- when: /* @__PURE__ */ __name((answers) => fs2.existsSync(getChoicesDirectory(answers)), "when"),
77
- type: "list",
78
- name,
79
- message: `Choose ${name}`,
80
- store: true,
81
- choices: /* @__PURE__ */ __name((answers) => [
82
- ...this.listSubDirectories(getChoicesDirectory(answers)),
83
- new inquirer2.Separator(),
84
- `Create new ${name}`
85
- ], "choices"),
86
- validate: required,
87
- filter: this.kebabCase
88
- },
89
- {
90
- when: /* @__PURE__ */ __name((answers) => !fs2.existsSync(getChoicesDirectory(answers)) || answers[name] ===
91
- `Create-new-${name}`, "when"),
92
- type: "input",
93
- name: `new-${name}`,
94
- message: `New ${name} name`,
95
- store: false,
96
- validate: /* @__PURE__ */ __name((input) => chain(input, required, filename), "validate"),
97
- filter: this.kebabCase
98
- },
99
- {
100
- when: /* @__PURE__ */ __name((answers) => !fs2.existsSync(getChoicesDirectory(answers)) || answers[name] ===
101
- "Create-new-tribe", "when"),
102
- type: "input",
103
- name: "costCenter",
104
- message: "Please provide the Cost Center of the Tribe",
105
- store: false,
106
- validate: /* @__PURE__ */ __name((input) => chain(input, required, filename), "validate"),
107
- filter: this.kebabCase
108
- }
109
- ];
110
- }
111
- };
112
- }
113
- });
1
+ const fg = require('glob');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const chalk = require('chalk');
5
+ const inquirer = require('inquirer');
6
+ const Separator = require('enquirer-separator');
7
+ const { Storage } = require('@google-cloud/storage');
8
+ const BaseGenerator = require('../../../src/BaseGenerator');
114
9
 
115
- // generators/maintenance/manage-states/index.js
116
- var fg = require("glob");
117
- var fs = require("fs");
118
- var path = require("path");
119
- var chalk = require("chalk");
120
- var inquirer = require("inquirer");
121
- var Separator = require("enquirer-separator");
122
- var { Storage } = require("@google-cloud/storage");
123
- var BaseGenerator = require_BaseGenerator();
124
- var getBucketName = /* @__PURE__ */ __name((answers) => {
10
+ const getBucketName = (answers) => {
125
11
  const dirName = path.basename(process.cwd());
126
- let bucketName = "";
127
- if (dirName === "tf-infra-gcp") {
128
- bucketName = "platform-tf-admin-prod";
129
- } else if (dirName.endsWith("-common")) {
130
- bucketName = `tf-state-${dirName.replace("-common", "")}-${answers.env}`;
12
+ let bucketName = '';
13
+ if (dirName === 'tf-infra-gcp') {
14
+ bucketName = 'platform-tf-admin-prod';
15
+ } else if (dirName.endsWith('-common')) {
16
+ bucketName = `tf-state-${dirName.replace('-common', '')}-${answers.env}`;
131
17
  } else {
132
18
  throw new Error(
133
- "Run this command from the root of tf-infra-gcp of -common repository"
19
+ 'Run this command from the root of tf-infra-gcp of -common repository',
134
20
  );
135
21
  }
136
22
  return bucketName;
137
- }, "getBucketName");
138
- var downloadStateFiles = /* @__PURE__ */ __name((files, dest) => {
23
+ };
24
+
25
+ const downloadStateFiles = (files, dest) => {
139
26
  files.forEach((file) => {
140
27
  const destFile = path.join(dest, file.name);
141
28
  const modTime = new Date(file.metadata.updated);
142
29
  fs.mkdirSync(path.dirname(destFile), { recursive: true });
143
30
  file.download({ destination: destFile }, () => {
144
31
  console.log(
145
- `gs://${file.bucket.name}/${file.name} [${chalk.magenta(file.metadata.size)}] (${chalk.yellow(file.metadata.updated.
146
- slice(0, 10))})`
32
+ `gs://${file.bucket.name}/${file.name} [${chalk.magenta(file.metadata.size)}] (${chalk.yellow(file.metadata.updated.slice(0, 10))})`,
147
33
  );
148
34
  fs.utimesSync(destFile, modTime, modTime);
149
35
  });
150
36
  });
151
- }, "downloadStateFiles");
37
+ };
38
+
152
39
  module.exports = class extends BaseGenerator {
153
40
  prompting() {
154
41
  const prompts = [
155
42
  {
156
- type: "list",
157
- name: "command",
158
- message: "Select operation to do",
43
+ type: 'list',
44
+ name: 'command',
45
+ message: 'Select operation to do',
159
46
  store: true,
160
47
  choices: [
161
48
  {
162
- name: "Search for orphan state files",
163
- value: "searchOrphanStates"
49
+ name: 'Search for orphan state files',
50
+ value: 'searchOrphanStates',
164
51
  },
165
52
  {
166
- name: "Download all state files",
167
- value: "downloadAll"
168
- }
169
- ]
53
+ name: 'Download all state files',
54
+ value: 'downloadAll',
55
+ },
56
+ ],
170
57
  },
58
+
171
59
  {
172
- type: "list",
173
- name: "env",
174
- message: "Select environment to work with",
60
+ type: 'list',
61
+ name: 'env',
62
+ message: 'Select environment to work with',
175
63
  store: true,
176
- choices: ["staging", "prod"],
177
- when: /* @__PURE__ */ __name(() => path.basename(process.cwd()).endsWith("-common"), "when")
64
+ choices: ['staging', 'prod'],
65
+ when: () => path.basename(process.cwd()).endsWith('-common'),
178
66
  },
67
+
179
68
  {
180
- type: "checkbox",
181
- name: "stateFiles",
182
- message: "Next state files are orphan",
183
- when: /* @__PURE__ */ __name(async (response) => response.command === "searchOrphanStates", "when"),
184
- choices: /* @__PURE__ */ __name(async (response) => {
69
+ type: 'checkbox',
70
+ name: 'stateFiles',
71
+ message: 'Next state files are orphan',
72
+ when: async (response) => response.command === 'searchOrphanStates',
73
+
74
+ choices: async (response) => {
185
75
  const constExpectedStates = [];
186
76
  const choices = [];
187
- if (path.basename(process.cwd()) === "tf-infra-gcp") {
77
+
78
+ if (path.basename(process.cwd()) === 'tf-infra-gcp') {
188
79
  const tgFiles = fg.sync(
189
- "organization/extendaretail-com/**/terragrunt.hcl",
190
- { dot: false }
80
+ 'organization/extendaretail-com/**/terragrunt.hcl',
81
+ { dot: false },
191
82
  );
192
83
  tgFiles.forEach((el) => {
193
- const genStateFile = el.replace(/^organization\//, "").replace("terragrunt.hcl", "default.tfstate");
84
+ const genStateFile = el
85
+ .replace(/^organization\//, '')
86
+ .replace('terragrunt.hcl', 'default.tfstate');
194
87
  constExpectedStates.push(genStateFile);
195
88
  });
196
89
  } else {
197
90
  const tgFiles = fg.sync(`infra/${response.env}/**/terragrunt.hcl`, {
198
- dot: false
91
+ dot: false,
199
92
  });
200
93
  tgFiles.forEach((el) => {
201
- const genStateFile = el.replace(/^infra\//, "").replace("terragrunt.hcl", "terraform.tfstate/default.tfsta\
202
- te");
94
+ const genStateFile = el
95
+ .replace(/^infra\//, '')
96
+ .replace('terragrunt.hcl', 'terraform.tfstate/default.tfstate');
203
97
  constExpectedStates.push(genStateFile);
204
98
  });
205
99
  }
100
+
206
101
  const storage = new Storage();
207
102
  const bucket = getBucketName(response);
208
- const [files] = await storage.bucket(bucket).getFiles().catch((err) => {
209
- console.log(
210
- chalk.red("Error occured during requesting the bucket:")
211
- );
212
- console.log(err.message);
213
- process.exit(1);
214
- });
103
+ const [files] = await storage
104
+ .bucket(bucket)
105
+ .getFiles()
106
+ .catch((err) => {
107
+ console.log(
108
+ chalk.red('Error occured during requesting the bucket:'),
109
+ );
110
+ console.log(err.message);
111
+ process.exit(1);
112
+ });
215
113
  await Promise.all(
216
- files.filter((file) => !constExpectedStates.includes(file.name)).map(async (file) => {
217
- let name = `${file.name} [${chalk.magenta(file.metadata.size)}] (${chalk.yellow(file.metadata.updated.slice(
218
- 0, 10))})`;
219
- if (file.name.endsWith(".tfstate")) {
220
- const stateData = JSON.parse(await file.download());
221
- if (stateData.resources.length === 0 || stateData.resources.every((i) => i.instances.length === 0)) {
222
- name = `${chalk.green("[empty]")} ${name}`;
114
+ files
115
+ .filter((file) => !constExpectedStates.includes(file.name))
116
+ .map(async (file) => {
117
+ let name = `${file.name} [${chalk.magenta(file.metadata.size)}] (${chalk.yellow(file.metadata.updated.slice(0, 10))})`;
118
+
119
+ if (file.name.endsWith('.tfstate')) {
120
+ const stateData = JSON.parse(await file.download());
121
+ if (
122
+ stateData.resources.length === 0 ||
123
+ stateData.resources.every((i) => i.instances.length === 0)
124
+ ) {
125
+ name = `${chalk.green('[empty]')} ${name}`;
126
+ } else {
127
+ name = `${chalk.red('[contains]')} ${name}`;
128
+ }
129
+ } else if (file.name.endsWith('.tflock')) {
130
+ name = `${chalk.red('[LOCK]')} ${name}`;
223
131
  } else {
224
- name = `${chalk.red("[contains]")} ${name}`;
132
+ name = `${chalk.yellowBright('[unknown]')} ${name}`;
225
133
  }
226
- } else if (file.name.endsWith(".tflock")) {
227
- name = `${chalk.red("[LOCK]")} ${name}`;
228
- } else {
229
- name = `${chalk.yellowBright("[unknown]")} ${name}`;
230
- }
231
- choices.push({
232
- name,
233
- value: file
234
- });
235
- })
134
+
135
+ choices.push({
136
+ name,
137
+ value: file,
138
+ });
139
+ }),
236
140
  );
141
+
237
142
  if (choices.length === 0) {
238
143
  this.log(
239
144
  chalk.green(
240
- "There are no orhan state files. All files have related terragrunt code in the repository"
241
- )
145
+ 'There are no orhan state files. All files have related terragrunt code in the repository',
146
+ ),
242
147
  );
243
148
  process.exit();
244
149
  }
245
- choices.sort((a, b) => a.value.name > b.value.name ? 1 : -1);
246
- choices.push(new Separator("------"));
150
+
151
+ choices.sort((a, b) => (a.value.name > b.value.name ? 1 : -1));
152
+ choices.push(new Separator('------'));
247
153
  return choices;
248
- }, "choices")
154
+ },
249
155
  },
156
+
250
157
  {
251
- type: "list",
252
- name: "subCommand",
253
- message: "What to do with selected files?",
254
- choices: ["nothing", "Download", "Delete"],
255
- default: "nothing",
256
- when: /* @__PURE__ */ __name((response) => response.command === "searchOrphanStates" && response.stateFiles.length >
257
- 0, "when")
158
+ type: 'list',
159
+ name: 'subCommand',
160
+ message: 'What to do with selected files?',
161
+ choices: ['nothing', 'Download', 'Delete'],
162
+ default: 'nothing',
163
+ when: (response) =>
164
+ response.command === 'searchOrphanStates' &&
165
+ response.stateFiles.length > 0,
258
166
  },
167
+
259
168
  {
260
- type: "input",
261
- name: "savePath",
262
- message: "Enter destination directory to save state files to",
263
- default: /* @__PURE__ */ __name(async (response) => response.env ? `download-states-${response.env}` : "download\
264
- -states", "default"),
265
- when: /* @__PURE__ */ __name(async (response) => response.command === "downloadAll" || response.subCommand === "\
266
- Download", "when")
267
- }
169
+ type: 'input',
170
+ name: 'savePath',
171
+ message: 'Enter destination directory to save state files to',
172
+ default: async (response) =>
173
+ response.env ? `download-states-${response.env}` : 'download-states',
174
+ when: async (response) =>
175
+ response.command === 'downloadAll' ||
176
+ response.subCommand === 'Download',
177
+ },
268
178
  ];
179
+
269
180
  return this.prompt(prompts).then((props) => {
270
181
  this.answers = props;
271
182
  });
272
183
  }
184
+
273
185
  writing() {
274
- if (this.answers.command === "searchOrphanStates" && this.answers.subCommand === "Download") {
186
+ if (
187
+ this.answers.command === 'searchOrphanStates' &&
188
+ this.answers.subCommand === 'Download'
189
+ ) {
275
190
  downloadStateFiles(this.answers.stateFiles, this.answers.savePath);
276
191
  }
277
- if (this.answers.command === "searchOrphanStates" && this.answers.subCommand === "Delete") {
278
- this.log(chalk.red("Next files is going to be deleted:"));
192
+
193
+ if (
194
+ this.answers.command === 'searchOrphanStates' &&
195
+ this.answers.subCommand === 'Delete'
196
+ ) {
197
+ this.log(chalk.red('Next files is going to be deleted:'));
279
198
  this.answers.stateFiles.forEach((file) => {
280
199
  this.log(
281
- `gs://${file.bucket.name}/${file.name} [${chalk.magenta(file.metadata.size)}] (${chalk.yellow(file.metadata.updated.
282
- slice(0, 10))})`
200
+ `gs://${file.bucket.name}/${file.name} [${chalk.magenta(file.metadata.size)}] (${chalk.yellow(file.metadata.updated.slice(0, 10))})`,
283
201
  );
284
202
  });
203
+
285
204
  const deleteQuestion = [
286
205
  {
287
- type: "confirm",
288
- name: "confirm",
289
- message: "Do you really want to delete them?",
290
- default: false
291
- }
206
+ type: 'confirm',
207
+ name: 'confirm',
208
+ message: 'Do you really want to delete them?',
209
+ default: false,
210
+ },
292
211
  ];
293
212
  inquirer.prompt(deleteQuestion).then((deleteAnswer) => {
294
213
  if (deleteAnswer.confirm === true) {
@@ -298,11 +217,15 @@ Download", "when")
298
217
  }
299
218
  });
300
219
  }
301
- if (this.answers.command === "downloadAll") {
220
+
221
+ if (this.answers.command === 'downloadAll') {
302
222
  const storage = new Storage();
303
- storage.bucket(getBucketName(this.answers)).getFiles().then(([files]) => {
304
- downloadStateFiles(files, this.answers.savePath);
305
- });
223
+ storage
224
+ .bucket(getBucketName(this.answers))
225
+ .getFiles()
226
+ .then(([files]) => {
227
+ downloadStateFiles(files, this.answers.savePath);
228
+ });
306
229
  }
307
230
  }
308
231
  };