@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
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
} =
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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,
|
|
16
|
+
const info = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
234
17
|
const name = path.basename(dir);
|
|
235
|
-
command
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
}
|
|
241
|
-
|
|
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(
|
|
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 =
|
|
251
|
-
description =
|
|
252
|
-
require
|
|
253
|
-
} = JSON.parse(fs.readFileSync(path.join(file),
|
|
254
|
-
const command = program
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
}
|
|
262
|
-
|
|
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
|
-
|
|
273
|
-
|
|
64
|
+
|
|
65
|
+
return createCommands(command)
|
|
66
|
+
.version(
|
|
67
|
+
`gcp-infra ${cliVersion}
|
|
274
68
|
gcp-infra-generators ${packageVersion}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
};
|