@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.
- package/dist/generators/clan-resources/clan-project/index.js +89 -189
- package/dist/generators/common-resources/bigquery/index.js +172 -267
- package/dist/generators/common-resources/budget/index.js +67 -153
- package/dist/generators/common-resources/cloud-armor/index.js +17 -167
- package/dist/generators/common-resources/cloud-storage/index.js +96 -205
- package/dist/generators/common-resources/cloudsql/index.js +71 -177
- package/dist/generators/common-resources/cloudsql-database/index.js +40 -287
- package/dist/generators/common-resources/confluent-cluster/index.js +23 -132
- package/dist/generators/common-resources/datastore/index.js +48 -194
- package/dist/generators/common-resources/elastic-cloud/index.js +22 -132
- package/dist/generators/common-resources/elastic-index-policy/handle-yaml.js +76 -0
- package/dist/generators/common-resources/elastic-index-policy/index.js +131 -286
- package/dist/generators/common-resources/elastic-template/index.js +52 -162
- package/dist/generators/common-resources/firestore/index.js +93 -233
- package/dist/generators/common-resources/iam/index.js +35 -157
- package/dist/generators/common-resources/iam/valid-prefix.js +8 -0
- package/dist/generators/common-resources/kafka-connect/index.js +35 -144
- package/dist/generators/common-resources/kafka-topics/index.js +20 -129
- package/dist/generators/common-resources/kms/index.js +31 -141
- package/dist/generators/common-resources/memorystore/index.js +42 -328
- package/dist/generators/common-resources/monitoring/handle-yaml.js +49 -0
- package/dist/generators/common-resources/monitoring/index.js +144 -322
- package/dist/generators/common-resources/monitoring/validate.js +58 -0
- package/dist/generators/common-resources/pubsub/append.js +130 -0
- package/dist/generators/common-resources/pubsub/get-gcp-projects.js +34 -0
- package/dist/generators/common-resources/pubsub/handle-subscribers.js +68 -0
- package/dist/generators/common-resources/pubsub/index.js +194 -536
- package/dist/generators/common-resources/pubsub/validate.js +53 -0
- package/dist/generators/common-resources/scheduler/append.js +85 -0
- package/dist/generators/common-resources/scheduler/index.js +62 -249
- package/dist/generators/common-resources/spanner/append.js +31 -0
- package/dist/generators/common-resources/spanner/index.js +102 -269
- package/dist/generators/common-resources/spanner/validate.js +38 -0
- package/dist/generators/docs/rca/index.js +25 -135
- package/dist/generators/docs/runbook/index.js +16 -126
- package/dist/generators/docs/srb/index.js +33 -147
- package/dist/generators/docs/srb/run-docker.js +2 -0
- package/dist/generators/init/clan-infra/gcp-projects.js +47 -0
- package/dist/generators/init/clan-infra/index.js +95 -290
- package/dist/generators/init/clan-infra/tribe-clan-repo.js +38 -0
- package/dist/generators/init/clan-infra/validate.js +8 -0
- package/dist/generators/maintenance/manage-states/index.js +142 -219
- package/dist/generators/maintenance/update-modules/index.js +56 -155
- package/dist/generators/organization/clan-project/googlecloud.js +124 -0
- package/dist/generators/organization/clan-project/index.js +81 -303
- package/dist/node_modules/.package-lock.json +81 -23
- package/dist/package.json +45 -0
- package/dist/src/BaseGenerator.js +84 -0
- package/dist/src/SecretsGenerator.js +137 -0
- package/dist/src/cli.js +54 -255
- package/dist/src/dependency-check.js +48 -0
- package/dist/src/update-check.js +38 -0
- package/dist/src/validators.js +33 -0
- package/dist/src/yeoman.js +80 -0
- package/package.json +1 -2
|
@@ -1,285 +1,114 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
});
|
|
114
|
-
|
|
115
|
-
// generators/common-resources/spanner/validate.js
|
|
116
|
-
var require_validate = __commonJS({
|
|
117
|
-
"generators/common-resources/spanner/validate.js"(exports2, module2) {
|
|
118
|
-
var validName2 = /* @__PURE__ */ __name((input) => {
|
|
119
|
-
if (input.replace(/\s/g, "").length >= 6 && input.length <= 30) {
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
return "Name must be between 6 and 30 characters in length";
|
|
123
|
-
}, "validName");
|
|
124
|
-
var validRetentionPeriod2 = /* @__PURE__ */ __name((input) => {
|
|
125
|
-
const validFormats = /^(84000s|1h|2d|7d)$/;
|
|
126
|
-
if (input === "") {
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
if (validFormats.test(input)) {
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
return "Invalid retention period format. Possible values are 84000s, 1h, 2d, or leave empty for default value 1h";
|
|
133
|
-
}, "validRetentionPeriod");
|
|
134
|
-
var validBackupSchedule2 = /* @__PURE__ */ __name((input) => {
|
|
135
|
-
const validFormats = /^(((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5}$/;
|
|
136
|
-
if (input === "") {
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
if (validFormats.test(input)) {
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
return 'Invalid backup schedule format. Possible values are cron expressions like "0 2 * * *"';
|
|
143
|
-
}, "validBackupSchedule");
|
|
144
|
-
module2.exports = {
|
|
145
|
-
validName: validName2,
|
|
146
|
-
validRetentionPeriod: validRetentionPeriod2,
|
|
147
|
-
validBackupSchedule: validBackupSchedule2
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// generators/common-resources/spanner/append.js
|
|
153
|
-
var require_append = __commonJS({
|
|
154
|
-
"generators/common-resources/spanner/append.js"(exports2, module2) {
|
|
155
|
-
var fs2 = require("fs");
|
|
156
|
-
var yaml = require("js-yaml");
|
|
157
|
-
var appendToDatabasesYaml2 = /* @__PURE__ */ __name((databasesYamlPath, newDbEntry) => {
|
|
158
|
-
const databases = [];
|
|
159
|
-
if (fs2.existsSync(databasesYamlPath)) {
|
|
160
|
-
const existingContent = fs2.readFileSync(databasesYamlPath, "utf8");
|
|
161
|
-
const existingDatabases = yaml.load(existingContent).databases;
|
|
162
|
-
databases.push(...existingDatabases);
|
|
163
|
-
}
|
|
164
|
-
const cleanNewDatabaseEntry = {
|
|
165
|
-
name: newDbEntry.name,
|
|
166
|
-
...newDbEntry.ddl ? { ddl: [newDbEntry.ddl] } : {},
|
|
167
|
-
...newDbEntry.retentionPeriod ? { version_retention_period: newDbEntry.retentionPeriod } : {},
|
|
168
|
-
...newDbEntry.backupSchedule ? { backup_schedule: newDbEntry.backupSchedule } : {}
|
|
169
|
-
};
|
|
170
|
-
databases.push(cleanNewDatabaseEntry);
|
|
171
|
-
const newYamlContent = yaml.dump({ databases }, { lineWidth: -1 });
|
|
172
|
-
fs2.writeFileSync(databasesYamlPath, newYamlContent, "utf8");
|
|
173
|
-
}, "appendToDatabasesYaml");
|
|
174
|
-
module2.exports = appendToDatabasesYaml2;
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// generators/common-resources/spanner/index.js
|
|
179
|
-
var path = require("path");
|
|
180
|
-
var chalk = require("chalk");
|
|
181
|
-
var fs = require("fs");
|
|
182
|
-
var BaseGenerator = require_BaseGenerator();
|
|
183
|
-
var { required } = require_validators();
|
|
184
|
-
var {
|
|
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 {
|
|
185
7
|
validName,
|
|
186
8
|
validRetentionPeriod,
|
|
187
|
-
validBackupSchedule
|
|
188
|
-
} =
|
|
189
|
-
|
|
9
|
+
validBackupSchedule,
|
|
10
|
+
} = require('./validate');
|
|
11
|
+
const appendToDatabasesYaml = require('./append');
|
|
12
|
+
|
|
190
13
|
module.exports = class extends BaseGenerator {
|
|
191
14
|
prompting() {
|
|
192
15
|
const prompts = [
|
|
193
16
|
{
|
|
194
|
-
type:
|
|
195
|
-
name:
|
|
196
|
-
message:
|
|
197
|
-
default:
|
|
198
|
-
choices: [
|
|
17
|
+
type: 'list',
|
|
18
|
+
name: 'resourceType',
|
|
19
|
+
message: 'Select the resource you want to create',
|
|
20
|
+
default: 'database',
|
|
21
|
+
choices: ['instance', 'database'],
|
|
199
22
|
},
|
|
200
23
|
{
|
|
201
|
-
when:
|
|
202
|
-
type:
|
|
203
|
-
name:
|
|
204
|
-
message:
|
|
205
|
-
|
|
206
|
-
default:
|
|
207
|
-
choices: [
|
|
24
|
+
when: (response) => response.resourceType === 'instance',
|
|
25
|
+
type: 'list',
|
|
26
|
+
name: 'regionalInstance',
|
|
27
|
+
message:
|
|
28
|
+
'Both staging and prod will get configuration for regional instance. If multi regional is needed contact platform team',
|
|
29
|
+
default: 'proceed',
|
|
30
|
+
choices: ['proceed'],
|
|
208
31
|
},
|
|
209
32
|
{
|
|
210
|
-
when:
|
|
211
|
-
type:
|
|
212
|
-
name:
|
|
213
|
-
message:
|
|
214
|
-
validate: validName
|
|
33
|
+
when: (response) => response.resourceType === 'instance',
|
|
34
|
+
type: 'input',
|
|
35
|
+
name: 'instanceName',
|
|
36
|
+
message: 'Please provide a name for the instance',
|
|
37
|
+
validate: validName,
|
|
215
38
|
},
|
|
216
39
|
{
|
|
217
|
-
when:
|
|
218
|
-
type:
|
|
219
|
-
name:
|
|
220
|
-
message:
|
|
221
|
-
|
|
40
|
+
when: (response) => response.resourceType === 'instance',
|
|
41
|
+
type: 'input',
|
|
42
|
+
name: 'displayName',
|
|
43
|
+
message:
|
|
44
|
+
'Please provide the descriptive name for this instance. Unique per project.',
|
|
45
|
+
validate: validName,
|
|
222
46
|
},
|
|
223
47
|
{
|
|
224
|
-
when:
|
|
225
|
-
type:
|
|
226
|
-
name:
|
|
227
|
-
message:
|
|
228
|
-
|
|
229
|
-
default:
|
|
230
|
-
choices: [
|
|
48
|
+
when: (response) => response.resourceType === 'instance',
|
|
49
|
+
type: 'list',
|
|
50
|
+
name: 'instanceAllocation',
|
|
51
|
+
message:
|
|
52
|
+
'Select the specified config you want to add for the instance. Only one of these can be present in terraform node_count or processing_units',
|
|
53
|
+
default: 'processing_units',
|
|
54
|
+
choices: ['processing_units', 'num_nodes'],
|
|
231
55
|
},
|
|
232
56
|
{
|
|
233
|
-
when:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
57
|
+
when: (response) =>
|
|
58
|
+
response.instanceAllocation === 'processing_units' &&
|
|
59
|
+
response.resourceType === 'instance',
|
|
60
|
+
type: 'input',
|
|
61
|
+
name: 'processingUnits',
|
|
62
|
+
message:
|
|
63
|
+
'Please provide the number of processing units allocated to the instance',
|
|
64
|
+
validate: required,
|
|
239
65
|
},
|
|
240
66
|
{
|
|
241
|
-
when:
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
67
|
+
when: (response) =>
|
|
68
|
+
response.instanceAllocation === 'num_nodes' &&
|
|
69
|
+
response.resourceType === 'instance',
|
|
70
|
+
type: 'input',
|
|
71
|
+
name: 'numNodes',
|
|
72
|
+
message: 'Please provide the number of nodes allocated to the instance',
|
|
73
|
+
validate: required,
|
|
247
74
|
},
|
|
248
75
|
{
|
|
249
|
-
when:
|
|
250
|
-
type:
|
|
251
|
-
name:
|
|
252
|
-
message:
|
|
253
|
-
validate: validName
|
|
76
|
+
when: (response) => response.resourceType === 'database',
|
|
77
|
+
type: 'input',
|
|
78
|
+
name: 'databaseName',
|
|
79
|
+
message: 'Please provide a name for the database',
|
|
80
|
+
validate: validName,
|
|
254
81
|
},
|
|
255
82
|
{
|
|
256
|
-
when:
|
|
257
|
-
type:
|
|
258
|
-
name:
|
|
259
|
-
message:
|
|
260
|
-
|
|
83
|
+
when: (response) => response.resourceType === 'database',
|
|
84
|
+
type: 'input',
|
|
85
|
+
name: 'ddl',
|
|
86
|
+
message:
|
|
87
|
+
'Please provide an optional list of DDL statements to run inside the newly created database. Leave empty to add them later.',
|
|
261
88
|
},
|
|
262
89
|
{
|
|
263
|
-
when:
|
|
264
|
-
type:
|
|
265
|
-
name:
|
|
266
|
-
message:
|
|
267
|
-
|
|
268
|
-
validate: validRetentionPeriod
|
|
90
|
+
when: (response) => response.resourceType === 'database',
|
|
91
|
+
type: 'input',
|
|
92
|
+
name: 'retentionPeriod',
|
|
93
|
+
message:
|
|
94
|
+
'Please provide version retention period. Maximum value 7d, possible values include 84000s, 1h, 2d. Leave empty for default value 1h.',
|
|
95
|
+
validate: validRetentionPeriod,
|
|
269
96
|
},
|
|
270
97
|
{
|
|
271
|
-
when:
|
|
272
|
-
type:
|
|
273
|
-
name:
|
|
274
|
-
message:
|
|
275
|
-
|
|
276
|
-
validate: validBackupSchedule
|
|
277
|
-
}
|
|
98
|
+
when: (response) => response.resourceType === 'database',
|
|
99
|
+
type: 'input',
|
|
100
|
+
name: 'backupSchedule',
|
|
101
|
+
message:
|
|
102
|
+
'Please provide backup schedule. Possible values are valid cron expressions like "0 2 * * *". Leave empty to add later.',
|
|
103
|
+
validate: validBackupSchedule,
|
|
104
|
+
},
|
|
278
105
|
];
|
|
106
|
+
|
|
279
107
|
return this.prompt(prompts).then((props) => {
|
|
280
108
|
this.answers = props;
|
|
281
109
|
});
|
|
282
110
|
}
|
|
111
|
+
|
|
283
112
|
writing() {
|
|
284
113
|
const {
|
|
285
114
|
resourceType,
|
|
@@ -289,14 +118,16 @@ ty to add later.',
|
|
|
289
118
|
databaseName,
|
|
290
119
|
ddl,
|
|
291
120
|
retentionPeriod,
|
|
292
|
-
backupSchedule
|
|
121
|
+
backupSchedule,
|
|
293
122
|
} = this.answers;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
const
|
|
123
|
+
|
|
124
|
+
['prod', 'staging'].forEach((env) => {
|
|
125
|
+
const spannerPath = path.join('infra', env, 'spanner');
|
|
126
|
+
const databasesYamlPath = path.join(spannerPath, 'databases.yaml');
|
|
127
|
+
const specPath = path.join(spannerPath, 'spec.hcl');
|
|
128
|
+
|
|
298
129
|
if (!fs.existsSync(specPath)) {
|
|
299
|
-
[
|
|
130
|
+
['terragrunt.hcl', 'spec.hcl'].forEach((file) => {
|
|
300
131
|
this.fs.copyTpl(
|
|
301
132
|
this.templatePath(`spanner/${file}`),
|
|
302
133
|
this.destinationPath(`${spannerPath}/${file}`),
|
|
@@ -310,13 +141,14 @@ ty to add later.',
|
|
|
310
141
|
databaseName,
|
|
311
142
|
ddl,
|
|
312
143
|
retentionPeriod,
|
|
313
|
-
backupSchedule
|
|
314
|
-
}
|
|
144
|
+
backupSchedule,
|
|
145
|
+
},
|
|
315
146
|
);
|
|
316
147
|
});
|
|
317
148
|
}
|
|
318
|
-
|
|
319
|
-
|
|
149
|
+
|
|
150
|
+
if (!fs.existsSync(databasesYamlPath) && resourceType === 'database') {
|
|
151
|
+
['terragrunt.hcl', 'databases.yaml'].forEach((file) => {
|
|
320
152
|
this.fs.copyTpl(
|
|
321
153
|
this.templatePath(`spanner/${file}`),
|
|
322
154
|
this.destinationPath(`${spannerPath}/${file}`),
|
|
@@ -325,27 +157,28 @@ ty to add later.',
|
|
|
325
157
|
databaseName,
|
|
326
158
|
ddl,
|
|
327
159
|
retentionPeriod,
|
|
328
|
-
backupSchedule
|
|
329
|
-
}
|
|
160
|
+
backupSchedule,
|
|
161
|
+
},
|
|
330
162
|
);
|
|
331
163
|
});
|
|
332
164
|
}
|
|
333
|
-
|
|
165
|
+
|
|
166
|
+
if (fs.existsSync(databasesYamlPath) && resourceType === 'database') {
|
|
334
167
|
const newDatabaseEntry = {
|
|
335
168
|
name: databaseName,
|
|
336
169
|
ddl,
|
|
337
170
|
retentionPeriod,
|
|
338
|
-
backupSchedule
|
|
171
|
+
backupSchedule,
|
|
339
172
|
};
|
|
340
173
|
appendToDatabasesYaml(databasesYamlPath, newDatabaseEntry);
|
|
341
174
|
}
|
|
342
175
|
});
|
|
343
176
|
}
|
|
177
|
+
|
|
344
178
|
end() {
|
|
345
179
|
this.log(`
|
|
346
|
-
${chalk.green(
|
|
347
|
-
${chalk.green(
|
|
348
|
-
|
|
349
|
-
${chalk.green("1.")} Push this change in a feature branch and open a pull request.`);
|
|
180
|
+
${chalk.green('Your Cloud Spanner resources have now been created.')}
|
|
181
|
+
${chalk.green('Make sure to create a database for your instance. Please add any other specifications supported by the module if needed')}
|
|
182
|
+
${chalk.green('1.')} Push this change in a feature branch and open a pull request.`);
|
|
350
183
|
}
|
|
351
184
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const validName = (input) => {
|
|
2
|
+
if (input.replace(/\s/g, '').length >= 6 && input.length <= 30) {
|
|
3
|
+
return true;
|
|
4
|
+
}
|
|
5
|
+
return 'Name must be between 6 and 30 characters in length';
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const validRetentionPeriod = (input) => {
|
|
9
|
+
const validFormats = /^(84000s|1h|2d|7d)$/;
|
|
10
|
+
|
|
11
|
+
if (input === '') {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (validFormats.test(input)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return 'Invalid retention period format. Possible values are 84000s, 1h, 2d, or leave empty for default value 1h';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const validBackupSchedule = (input) => {
|
|
22
|
+
const validFormats = /^(((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5}$/;
|
|
23
|
+
|
|
24
|
+
if (input === '') {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (validFormats.test(input)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return 'Invalid backup schedule format. Possible values are cron expressions like "0 2 * * *"';
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
validName,
|
|
36
|
+
validRetentionPeriod,
|
|
37
|
+
validBackupSchedule,
|
|
38
|
+
};
|
|
@@ -1,159 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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 path = 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 path.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 path = require("path");
|
|
48
|
-
var fs = 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 = path.resolve(path.join(__dirname, ".."));
|
|
55
|
-
this.destinationRoot(process.cwd());
|
|
56
|
-
const [command, generator] = opts.namespace.split(":").slice(-2);
|
|
57
|
-
this.generatorId = path.join(command, generator);
|
|
58
|
-
this.sourceRoot(
|
|
59
|
-
path.join(this.baseDir, "generators", this.generatorId, "templates")
|
|
60
|
-
);
|
|
61
|
-
this.copyDir = (templateDir, targetDir, answers = this.answers, skipIfExists = false) => {
|
|
62
|
-
if (skipIfExists && fs.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) => fs.readdirSync(parent).filter((f) => !f.startsWith(".")).filter((f) => fs.
|
|
72
|
-
lstatSync(path.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) => fs.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) => !fs.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) => !fs.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 chalk = require('chalk');
|
|
2
|
+
const BaseGenerator = require('../../../src/BaseGenerator');
|
|
3
|
+
const { required } = require('../../../src/validators');
|
|
114
4
|
|
|
115
|
-
// generators/docs/rca/index.js
|
|
116
|
-
var chalk = require("chalk");
|
|
117
|
-
var BaseGenerator = require_BaseGenerator();
|
|
118
|
-
var { required } = require_validators();
|
|
119
5
|
module.exports = class extends BaseGenerator {
|
|
120
6
|
prompting() {
|
|
121
7
|
const prompts = [
|
|
122
8
|
{
|
|
123
|
-
type:
|
|
124
|
-
name:
|
|
125
|
-
message:
|
|
126
|
-
validate: required
|
|
9
|
+
type: 'input',
|
|
10
|
+
name: 'description',
|
|
11
|
+
message: 'A very short description of the problem',
|
|
12
|
+
validate: required,
|
|
127
13
|
},
|
|
128
14
|
{
|
|
129
|
-
type:
|
|
130
|
-
name:
|
|
131
|
-
message:
|
|
132
|
-
validate: required
|
|
133
|
-
}
|
|
15
|
+
type: 'input',
|
|
16
|
+
name: 'date',
|
|
17
|
+
message: 'Date of the incident',
|
|
18
|
+
validate: required,
|
|
19
|
+
},
|
|
134
20
|
];
|
|
21
|
+
|
|
135
22
|
return this.prompt(prompts).then((props) => {
|
|
136
23
|
this.answers = props;
|
|
137
24
|
});
|
|
138
25
|
}
|
|
26
|
+
|
|
139
27
|
writing() {
|
|
140
28
|
const { date } = this.answers;
|
|
141
|
-
const filenameInternal =
|
|
142
|
-
const filenameExternal =
|
|
29
|
+
const filenameInternal = 'rca_internal';
|
|
30
|
+
const filenameExternal = 'rca_external';
|
|
31
|
+
|
|
143
32
|
this.fs.copyTpl(
|
|
144
|
-
this.templatePath(
|
|
145
|
-
this.destinationPath(
|
|
146
|
-
this.answers
|
|
33
|
+
this.templatePath('docs', 'rca_internal.md'),
|
|
34
|
+
this.destinationPath('docs', 'rca', date, `${filenameInternal}.md`),
|
|
35
|
+
this.answers,
|
|
147
36
|
);
|
|
148
37
|
this.fs.copyTpl(
|
|
149
|
-
this.templatePath(
|
|
150
|
-
this.destinationPath(
|
|
151
|
-
this.answers
|
|
38
|
+
this.templatePath('docs', 'rca_external.md'),
|
|
39
|
+
this.destinationPath('docs', 'rca', date, `${filenameExternal}.md`),
|
|
40
|
+
this.answers,
|
|
152
41
|
);
|
|
153
42
|
}
|
|
43
|
+
|
|
154
44
|
end() {
|
|
155
45
|
this.log(`
|
|
156
|
-
${chalk.green(
|
|
46
|
+
${chalk.green('Your RCA template have now been created.')}
|
|
157
47
|
Next, push this change in a feature branch and open a pull request.
|
|
158
48
|
`);
|
|
159
49
|
}
|