@znemz/cfn-include 1.6.4 → 2.0.0
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/LICENSE +1 -1
- package/README.md +602 -21
- package/bin/cli.js +163 -110
- package/index.js +597 -190
- package/lib/cfnclient.js +42 -19
- package/lib/include/api.js +2 -3
- package/lib/parselocation.js +6 -2
- package/lib/promise.js +19 -24
- package/lib/replaceEnv.js +17 -11
- package/lib/schema.js +58 -9
- package/lib/yaml.js +11 -15
- package/package.json +62 -38
package/bin/cli.js
CHANGED
|
@@ -1,138 +1,191 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable global-require, no-console */
|
|
3
|
+
const exec = require('child_process').execSync;
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const _ = require('lodash');
|
|
6
|
+
const pathParse = require('path-parse');
|
|
7
|
+
const yargs = require('yargs');
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const include = require('../index');
|
|
10
|
+
const yaml = require('../lib/yaml');
|
|
11
|
+
const Client = require('../lib/cfnclient');
|
|
12
|
+
const pkg = require('../package.json');
|
|
13
|
+
const replaceEnv = require('../lib/replaceEnv');
|
|
14
|
+
|
|
15
|
+
yargs.version(false);
|
|
16
|
+
|
|
17
|
+
const { env } = process;
|
|
18
|
+
// eslint-disable-next-line global-require
|
|
19
|
+
const opts = yargs
|
|
20
|
+
.command('$0 [path] [options]', pkg.description, (y) =>
|
|
21
|
+
y.positional('path', {
|
|
14
22
|
positional: true,
|
|
15
23
|
desc: 'location of template. Either path to a local file, URL or file on an S3 bucket (e.g. s3://bucket-name/example.template)',
|
|
16
24
|
required: false,
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
25
|
+
})
|
|
26
|
+
)
|
|
27
|
+
.options({
|
|
28
|
+
minimize: {
|
|
29
|
+
desc: 'minimize JSON output',
|
|
30
|
+
default: false,
|
|
31
|
+
boolean: true,
|
|
32
|
+
alias: 'm',
|
|
33
|
+
},
|
|
34
|
+
metadata: {
|
|
35
|
+
desc: 'add build metadata to output',
|
|
36
|
+
default: false,
|
|
37
|
+
boolean: true,
|
|
38
|
+
},
|
|
39
|
+
validate: {
|
|
40
|
+
desc: 'validate compiled template',
|
|
41
|
+
default: false,
|
|
42
|
+
boolean: true,
|
|
43
|
+
alias: 't',
|
|
44
|
+
},
|
|
45
|
+
yaml: {
|
|
46
|
+
desc: 'output yaml instead of json',
|
|
47
|
+
default: false,
|
|
48
|
+
boolean: true,
|
|
49
|
+
alias: 'y',
|
|
50
|
+
},
|
|
51
|
+
lineWidth: {
|
|
52
|
+
desc: 'output yaml line width',
|
|
53
|
+
default: 200,
|
|
54
|
+
number: true,
|
|
55
|
+
alias: 'l',
|
|
56
|
+
},
|
|
57
|
+
bucket: {
|
|
58
|
+
desc: 'bucket name required for templates larger than 50k',
|
|
59
|
+
},
|
|
60
|
+
context: {
|
|
61
|
+
desc:
|
|
62
|
+
// eslint-disable-next-line max-len
|
|
63
|
+
'template full path. only utilized for stdin when the template is piped to this script',
|
|
64
|
+
required: false,
|
|
65
|
+
string: true,
|
|
66
|
+
},
|
|
67
|
+
prefix: {
|
|
68
|
+
desc: 'prefix for templates uploaded to the bucket',
|
|
69
|
+
default: 'cfn-include',
|
|
70
|
+
},
|
|
71
|
+
enable: {
|
|
72
|
+
string: true,
|
|
73
|
+
desc: `enable different options: ['env','eval'] or a combination of both via comma.`,
|
|
74
|
+
choices: ['', 'env', 'env,eval', 'eval,env', 'eval'], // '' hack
|
|
75
|
+
default: '',
|
|
76
|
+
},
|
|
77
|
+
inject: {
|
|
78
|
+
alias: 'i',
|
|
79
|
+
string: true,
|
|
80
|
+
// eslint-disable-next-line max-len
|
|
81
|
+
desc: `JSON string payload to use for template injection.`,
|
|
82
|
+
coerce: (valStr) => JSON.parse(valStr),
|
|
83
|
+
},
|
|
84
|
+
doLog: {
|
|
85
|
+
boolean: true,
|
|
86
|
+
// eslint-disable-next-line max-len
|
|
87
|
+
desc: `console log out include options in recurse step`,
|
|
88
|
+
},
|
|
89
|
+
version: {
|
|
90
|
+
boolean: true,
|
|
91
|
+
desc: 'print version and exit',
|
|
92
|
+
callback() {
|
|
93
|
+
console.log(pkg.version);
|
|
94
|
+
process.exit(0);
|
|
66
95
|
},
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
.parse();
|
|
99
|
+
|
|
100
|
+
// make enable an array
|
|
101
|
+
opts.enable = opts.enable.split(',');
|
|
71
102
|
|
|
72
|
-
|
|
103
|
+
let promise;
|
|
73
104
|
if (opts.path) {
|
|
74
|
-
|
|
105
|
+
let location;
|
|
106
|
+
const protocol = opts.path.match(/^\w+:\/\//);
|
|
75
107
|
if (protocol) location = opts.path;
|
|
76
|
-
else if (pathParse(opts.path).root) location =
|
|
77
|
-
else location =
|
|
108
|
+
else if (pathParse(opts.path).root) location = `file://${opts.path}`;
|
|
109
|
+
else location = `file://${path.join(process.cwd(), opts.path)}`;
|
|
78
110
|
promise = include({
|
|
79
111
|
url: location,
|
|
80
|
-
doEnv: opts.enable
|
|
112
|
+
doEnv: opts.enable.includes('env'),
|
|
113
|
+
doEval: opts.enable.includes('eval'),
|
|
114
|
+
inject: opts.inject,
|
|
115
|
+
doLog: opts.doLog,
|
|
81
116
|
});
|
|
82
117
|
} else {
|
|
83
118
|
promise = new Promise((resolve, reject) => {
|
|
84
119
|
process.stdin.setEncoding('utf8');
|
|
85
|
-
|
|
86
|
-
process.stdin.on('data', chunk => rawData.push(chunk));
|
|
87
|
-
process.stdin.on('error', err => reject(err));
|
|
120
|
+
const rawData = [];
|
|
121
|
+
process.stdin.on('data', (chunk) => rawData.push(chunk));
|
|
122
|
+
process.stdin.on('error', (err) => reject(err));
|
|
88
123
|
process.stdin.on('end', () => resolve(rawData.join('')));
|
|
89
|
-
}).then(template => {
|
|
124
|
+
}).then((template) => {
|
|
90
125
|
if (template.length === 0) {
|
|
91
126
|
console.error('empty template received from stdin');
|
|
92
127
|
process.exit(1);
|
|
93
128
|
}
|
|
94
129
|
|
|
95
|
-
const location = opts.context
|
|
96
|
-
path.
|
|
130
|
+
const location = opts.context
|
|
131
|
+
? path.resolve(opts.context)
|
|
132
|
+
: path.join(process.cwd(), 'template.yml');
|
|
133
|
+
|
|
134
|
+
template = opts.enable.includes('env') ? replaceEnv(template) : template;
|
|
97
135
|
|
|
98
|
-
template = opts.enable === 'env' ? replaceEnv(template) : template;
|
|
99
|
-
|
|
100
136
|
return include({
|
|
101
137
|
template: yaml.load(template),
|
|
102
|
-
url:
|
|
103
|
-
doEnv: opts.enable
|
|
104
|
-
|
|
138
|
+
url: `file://${location}`,
|
|
139
|
+
doEnv: opts.enable.includes('env'),
|
|
140
|
+
doEval: opts.enable.includes('eval'),
|
|
141
|
+
inject: opts.inject,
|
|
142
|
+
doLog: opts.doLog,
|
|
143
|
+
}).catch((err) => console.error(err));
|
|
105
144
|
});
|
|
106
145
|
}
|
|
107
146
|
|
|
108
|
-
promise
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
147
|
+
promise
|
|
148
|
+
.then(function (template) {
|
|
149
|
+
if (opts.metadata) {
|
|
150
|
+
let stdout;
|
|
151
|
+
try {
|
|
152
|
+
stdout = exec('git log -n 1 --pretty=%H', {
|
|
153
|
+
stdio: [0, 'pipe', 'ignore'],
|
|
154
|
+
})
|
|
155
|
+
.toString()
|
|
156
|
+
.trim();
|
|
157
|
+
} catch (e) {
|
|
158
|
+
// eslint-disable-next-line no-empty
|
|
121
159
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
160
|
+
_.defaultsDeep(template, {
|
|
161
|
+
Metadata: {
|
|
162
|
+
CfnInclude: {
|
|
163
|
+
GitCommit: stdout,
|
|
164
|
+
BuildDate: new Date().toISOString(),
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (opts.validate) {
|
|
170
|
+
const cfn = new Client({
|
|
171
|
+
region: env.AWS_REGION || env.AWS_DEFAULT_REGION || 'us-east-1',
|
|
172
|
+
bucket: opts.bucket,
|
|
173
|
+
prefix: opts.prefix,
|
|
174
|
+
});
|
|
175
|
+
return cfn.validateTemplate(JSON.stringify(template)).then(() => template);
|
|
176
|
+
}
|
|
177
|
+
return template;
|
|
178
|
+
})
|
|
179
|
+
.then((template) => {
|
|
180
|
+
console.log(
|
|
181
|
+
opts.yaml
|
|
182
|
+
? yaml.dump(template, opts)
|
|
183
|
+
: JSON.stringify(template, null, opts.minimize ? null : 2)
|
|
184
|
+
);
|
|
185
|
+
})
|
|
186
|
+
.catch(function (err) {
|
|
187
|
+
if (typeof err.toString === 'function') console.error(err.toString());
|
|
188
|
+
else console.error(err);
|
|
189
|
+
console.log(err.stack);
|
|
190
|
+
process.exit(1);
|
|
191
|
+
});
|