@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,53 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const validSystemName = (input) => {
5
+ if (input.replace(/\s/g, '').length === 3) {
6
+ return true;
7
+ }
8
+ return 'System name must be 3 characters';
9
+ };
10
+
11
+ const validVersion = (input) => {
12
+ const regex = '^v[0-9]$';
13
+ if (input.match(regex)) {
14
+ return true;
15
+ }
16
+ return 'Not supported input of version';
17
+ };
18
+
19
+ const validSubscriberName = (input) => {
20
+ const systemName = input.split('.')[0];
21
+ const serviceName = input.split('.')[1];
22
+ const serviceNameRexep = '^[a-zA-Z-_]+$';
23
+
24
+ if (
25
+ systemName.replace(/\s/g, '').length === 3 &&
26
+ serviceName.match(serviceNameRexep)
27
+ ) {
28
+ return true;
29
+ }
30
+ return 'Not supported input for subscriber name';
31
+ };
32
+
33
+ const checkExistingTopicPath = (input) => {
34
+ const topicDirPath = path.join(
35
+ process.cwd(),
36
+ 'infra',
37
+ 'staging',
38
+ 'pubsub',
39
+ input,
40
+ );
41
+
42
+ if (fs.existsSync(topicDirPath)) {
43
+ return true;
44
+ }
45
+ return 'Topic does not exist. Check the spelling';
46
+ };
47
+
48
+ module.exports = {
49
+ validSystemName,
50
+ validVersion,
51
+ validSubscriberName,
52
+ checkExistingTopicPath,
53
+ };
@@ -0,0 +1,85 @@
1
+ const fs = require('fs');
2
+
3
+ const findScheduledJobs = (schedulerPath) => {
4
+ const fileContent = fs.readFileSync(schedulerPath, 'utf8');
5
+ const regex = /scheduled_jobs\s*=\s*\[\s*([\s\S]*?)\s*\]/;
6
+ const match = regex.exec(fileContent);
7
+ if (match) {
8
+ const scheduledJobsText = match[1];
9
+ return scheduledJobsText;
10
+ }
11
+ return '';
12
+ };
13
+
14
+ const writeScheduledJobs = (schedulerPath, scheduledJobs) => {
15
+ const fileContent = fs.readFileSync(schedulerPath, 'utf8');
16
+ const updatedContent = fileContent.replace(
17
+ /scheduled_jobs\s*=\s*\[([\s\S]*?)\]/,
18
+ `scheduled_jobs = [\n ${scheduledJobs}\n ]`,
19
+ );
20
+ fs.writeFileSync(schedulerPath, updatedContent);
21
+ };
22
+
23
+ const scheduledJobsToHCL = (scheduledJobs) =>
24
+ `${scheduledJobs
25
+ .map((job) => {
26
+ const httpTargetBlock = job.http_target
27
+ ? `
28
+ http_target = {
29
+ uri = "${job.http_target.uri}"
30
+ http_method = "${job.http_target.http_method}"
31
+ }
32
+ }`
33
+ : '';
34
+ const pubsubTargetBlock = job.pubsub_target
35
+ ? `
36
+ pubsub_target = {
37
+ topic_name = "${job.pubsub_target.topic_name}"
38
+ data = "${job.pubsub_target.data}"
39
+ }
40
+ }`
41
+ : '';
42
+ return `
43
+ {
44
+ name = "${job.name}"
45
+ description = "${job.description}"
46
+ schedule = "${job.schedule}"
47
+ ${httpTargetBlock}${pubsubTargetBlock}`;
48
+ })
49
+ .join('\n')}`;
50
+
51
+ const handleJobs = (schedulerPath, answers) => {
52
+ const oldJobs = findScheduledJobs(schedulerPath);
53
+ const allJobs = [oldJobs];
54
+
55
+ if (answers.target === 'http') {
56
+ const newHttpJob = {
57
+ name: answers.name,
58
+ description: answers.description,
59
+ schedule: answers.schedule,
60
+ http_target: {
61
+ uri: answers.uri,
62
+ http_method: answers.httpMethod,
63
+ },
64
+ };
65
+
66
+ const newHttpJobHcl = scheduledJobsToHCL([newHttpJob]);
67
+ allJobs.push(newHttpJobHcl);
68
+ } else {
69
+ const newPubsubJob = {
70
+ name: answers.name,
71
+ description: answers.description,
72
+ schedule: answers.schedule,
73
+ pubsub_target: {
74
+ topic_name: answers.topicName,
75
+ data: answers.data,
76
+ },
77
+ };
78
+ const newPubsubJobHcl = scheduledJobsToHCL([newPubsubJob]);
79
+ allJobs.push(newPubsubJobHcl);
80
+ }
81
+
82
+ writeScheduledJobs(schedulerPath, allJobs);
83
+ };
84
+
85
+ module.exports = handleJobs;
@@ -1,292 +1,105 @@
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 inquirer = require("inquirer");
50
- var { chain, required: required2, 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 inquirer.Separator(),
84
- `Create new ${name}`
85
- ], "choices"),
86
- validate: required2,
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, required2, 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, required2, filename), "validate"),
107
- filter: this.kebabCase
108
- }
109
- ];
110
- }
111
- };
112
- }
113
- });
1
+ const path = require('path');
2
+ const chalk = require('chalk');
3
+ const fs = require('fs');
4
+ const BaseGenerator = require('../../../src/BaseGenerator');
5
+ const { required } = require('../../../src/validators');
6
+ const handleJobs = require('./append');
114
7
 
115
- // generators/common-resources/scheduler/append.js
116
- var require_append = __commonJS({
117
- "generators/common-resources/scheduler/append.js"(exports2, module2) {
118
- var fs2 = require("fs");
119
- var findScheduledJobs = /* @__PURE__ */ __name((schedulerPath) => {
120
- const fileContent = fs2.readFileSync(schedulerPath, "utf8");
121
- const regex = /scheduled_jobs\s*=\s*\[\s*([\s\S]*?)\s*\]/;
122
- const match = regex.exec(fileContent);
123
- if (match) {
124
- const scheduledJobsText = match[1];
125
- return scheduledJobsText;
126
- }
127
- return "";
128
- }, "findScheduledJobs");
129
- var writeScheduledJobs = /* @__PURE__ */ __name((schedulerPath, scheduledJobs) => {
130
- const fileContent = fs2.readFileSync(schedulerPath, "utf8");
131
- const updatedContent = fileContent.replace(
132
- /scheduled_jobs\s*=\s*\[([\s\S]*?)\]/,
133
- `scheduled_jobs = [
134
- ${scheduledJobs}
135
- ]`
136
- );
137
- fs2.writeFileSync(schedulerPath, updatedContent);
138
- }, "writeScheduledJobs");
139
- var scheduledJobsToHCL = /* @__PURE__ */ __name((scheduledJobs) => `${scheduledJobs.map((job) => {
140
- const httpTargetBlock = job.http_target ? `
141
- http_target = {
142
- uri = "${job.http_target.uri}"
143
- http_method = "${job.http_target.http_method}"
144
- }
145
- }` : "";
146
- const pubsubTargetBlock = job.pubsub_target ? `
147
- pubsub_target = {
148
- topic_name = "${job.pubsub_target.topic_name}"
149
- data = "${job.pubsub_target.data}"
150
- }
151
- }` : "";
152
- return `
153
- {
154
- name = "${job.name}"
155
- description = "${job.description}"
156
- schedule = "${job.schedule}"
157
- ${httpTargetBlock}${pubsubTargetBlock}`;
158
- }).join("\n")}`, "scheduledJobsToHCL");
159
- var handleJobs2 = /* @__PURE__ */ __name((schedulerPath, answers) => {
160
- const oldJobs = findScheduledJobs(schedulerPath);
161
- const allJobs = [oldJobs];
162
- if (answers.target === "http") {
163
- const newHttpJob = {
164
- name: answers.name,
165
- description: answers.description,
166
- schedule: answers.schedule,
167
- http_target: {
168
- uri: answers.uri,
169
- http_method: answers.httpMethod
170
- }
171
- };
172
- const newHttpJobHcl = scheduledJobsToHCL([newHttpJob]);
173
- allJobs.push(newHttpJobHcl);
174
- } else {
175
- const newPubsubJob = {
176
- name: answers.name,
177
- description: answers.description,
178
- schedule: answers.schedule,
179
- pubsub_target: {
180
- topic_name: answers.topicName,
181
- data: answers.data
182
- }
183
- };
184
- const newPubsubJobHcl = scheduledJobsToHCL([newPubsubJob]);
185
- allJobs.push(newPubsubJobHcl);
186
- }
187
- writeScheduledJobs(schedulerPath, allJobs);
188
- }, "handleJobs");
189
- module2.exports = handleJobs2;
190
- }
191
- });
192
-
193
- // generators/common-resources/scheduler/index.js
194
- var path = require("path");
195
- var chalk = require("chalk");
196
- var fs = require("fs");
197
- var BaseGenerator = require_BaseGenerator();
198
- var { required } = require_validators();
199
- var handleJobs = require_append();
200
8
  module.exports = class extends BaseGenerator {
201
9
  prompting() {
202
10
  const prompts = [
203
11
  {
204
- type: "input",
205
- name: "name",
206
- message: "Please provide the name of the job",
207
- validate: required
12
+ type: 'input',
13
+ name: 'name',
14
+ message: 'Please provide the name of the job',
15
+ validate: required,
208
16
  },
209
17
  {
210
- type: "input",
211
- name: "description",
212
- message: "Please provide the description for the job",
213
- validate: required
18
+ type: 'input',
19
+ name: 'description',
20
+ message: 'Please provide the description for the job',
21
+ validate: required,
214
22
  },
215
23
  {
216
- type: "list",
217
- name: "timeZone",
218
- message: "Please select the time zone to be used in interpreting schedule",
219
- default: "Etc/UTC",
220
- choices: ["Etc/UTC", "Etc/GMT"]
24
+ type: 'list',
25
+ name: 'timeZone',
26
+ message:
27
+ 'Please select the time zone to be used in interpreting schedule',
28
+ default: 'Etc/UTC',
29
+ choices: ['Etc/UTC', 'Etc/GMT'],
221
30
  },
222
31
  {
223
- type: "input",
224
- name: "schedule",
225
- message: "Please provide the schedule on which the job will be executed(unix-cron format - * * * * *)",
226
- validate: required
32
+ type: 'input',
33
+ name: 'schedule',
34
+ message:
35
+ 'Please provide the schedule on which the job will be executed(unix-cron format - * * * * *)',
36
+ validate: required,
227
37
  },
228
38
  {
229
- type: "list",
230
- name: "target",
231
- message: "Select the target for the job",
232
- choices: ["http", "pubsub"]
39
+ type: 'list',
40
+ name: 'target',
41
+ message: 'Select the target for the job',
42
+ choices: ['http', 'pubsub'],
233
43
  },
234
44
  {
235
- when: /* @__PURE__ */ __name((response) => response.target === "http", "when"),
236
- type: "input",
237
- name: "uri",
238
- message: "Please provide the full URI path that the request will be send to",
239
- validate: required
45
+ when: (response) => response.target === 'http',
46
+ type: 'input',
47
+ name: 'uri',
48
+ message:
49
+ 'Please provide the full URI path that the request will be send to',
50
+ validate: required,
240
51
  },
241
52
  {
242
- when: /* @__PURE__ */ __name((response) => response.target === "http", "when"),
243
- type: "input",
244
- name: "httpMethod",
245
- message: "Please provide which HTTP method to use for the request",
246
- validate: required
53
+ when: (response) => response.target === 'http',
54
+ type: 'input',
55
+ name: 'httpMethod',
56
+ message: 'Please provide which HTTP method to use for the request',
57
+ validate: required,
247
58
  },
248
59
  {
249
- when: /* @__PURE__ */ __name((response) => response.target === "pubsub", "when"),
250
- type: "input",
251
- name: "topicName",
252
- message: "Please provide the full Pub/Sub topic name",
253
- validate: required
60
+ when: (response) => response.target === 'pubsub',
61
+ type: 'input',
62
+ name: 'topicName',
63
+ message: 'Please provide the full Pub/Sub topic name',
64
+ validate: required,
254
65
  },
255
66
  {
256
- when: /* @__PURE__ */ __name((response) => response.target === "pubsub", "when"),
257
- type: "input",
258
- name: "data",
259
- message: "Please provide the message payload for Pub/Sub message",
260
- validate: required
261
- }
67
+ when: (response) => response.target === 'pubsub',
68
+ type: 'input',
69
+ name: 'data',
70
+ message: 'Please provide the message payload for Pub/Sub message',
71
+ validate: required,
72
+ },
262
73
  ];
74
+
263
75
  return this.prompt(prompts).then((props) => {
264
76
  this.answers = props;
265
77
  });
266
78
  }
79
+
267
80
  writing() {
268
- ["prod", "staging"].forEach((env) => {
81
+ ['prod', 'staging'].forEach((env) => {
269
82
  const schedulerPath = path.join(
270
83
  process.cwd(),
271
- "infra",
84
+ 'infra',
272
85
  env,
273
- "scheduler",
274
- "terragrunt.hcl"
86
+ 'scheduler',
87
+ 'terragrunt.hcl',
275
88
  );
276
89
  if (!fs.existsSync(schedulerPath)) {
277
- this.copyDir("scheduler", path.join("infra", env, "scheduler"), {
90
+ this.copyDir('scheduler', path.join('infra', env, 'scheduler'), {
278
91
  ...this.answers,
279
- env
92
+ env,
280
93
  });
281
94
  } else {
282
95
  handleJobs(schedulerPath, this.answers);
283
96
  }
284
97
  });
285
98
  }
99
+
286
100
  end() {
287
101
  this.log(`
288
- ${chalk.green("Your job resources have now been created. Please add any other specifications supported by the module if \
289
- needed")}
290
- ${chalk.green("1.")} Push this change in a feature branch and open a pull request.`);
102
+ ${chalk.green('Your job resources have now been created. Please add any other specifications supported by the module if needed')}
103
+ ${chalk.green('1.')} Push this change in a feature branch and open a pull request.`);
291
104
  }
292
105
  };
@@ -0,0 +1,31 @@
1
+ const fs = require('fs');
2
+ const yaml = require('js-yaml');
3
+
4
+ const appendToDatabasesYaml = (databasesYamlPath, newDbEntry) => {
5
+ const databases = [];
6
+ if (fs.existsSync(databasesYamlPath)) {
7
+ const existingContent = fs.readFileSync(databasesYamlPath, 'utf8');
8
+ const existingDatabases = yaml.load(existingContent).databases;
9
+ databases.push(...existingDatabases);
10
+ }
11
+
12
+ // Exclude empty fields from newDbEntry
13
+ const cleanNewDatabaseEntry = {
14
+ name: newDbEntry.name,
15
+ ...(newDbEntry.ddl ? { ddl: [newDbEntry.ddl] } : {}),
16
+ ...(newDbEntry.retentionPeriod
17
+ ? { version_retention_period: newDbEntry.retentionPeriod }
18
+ : {}),
19
+ ...(newDbEntry.backupSchedule
20
+ ? { backup_schedule: newDbEntry.backupSchedule }
21
+ : {}),
22
+ };
23
+
24
+ databases.push(cleanNewDatabaseEntry);
25
+
26
+ const newYamlContent = yaml.dump({ databases }, { lineWidth: -1 });
27
+
28
+ fs.writeFileSync(databasesYamlPath, newYamlContent, 'utf8');
29
+ };
30
+
31
+ module.exports = appendToDatabasesYaml;