forked from jdhornsby/terraunit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
terraunit.js
143 lines (119 loc) · 4.81 KB
/
terraunit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const MockAWS = require('./mock-aws-api');
const fs = require('fs').promises;
const path = require('path');
const execa = require('execa');
const { DEBUG_MODE, isDebugModeOn } = require('./utils');
const portfinder = require('portfinder-sync');
function Terraunit(options = {}) {
if (!options.port) {
options.port = portfinder.getPort(9000 + Math.floor(Math.random() * Math.floor(999)));
}
this.mockAws = new MockAWS(options);
this.debugMode = options.debugMode || DEBUG_MODE.LOCAL;
this.unitName = options.unitName || '';
this.start = () => {
this.mockAws.start();
};
this.stop = async () => {
await this.mockAws.stop();
};
this.plan = async (options) => {
const {
workingDirectory = process.cwd(),
configurations = []
} = options || {};
for (configuration of configurations) {
if (!configuration.content) {
configuration.content = '';
}
if (!configuration.fileName) {
configuration.fileName = 'main.tf';
}
if (configuration.mockProviderType === 'aws') {
configuration.content = await this._getMockAWSProvider(configuration.mockProviderAlias);
}
}
const files = new Set();
try {
const dir = path.join(workingDirectory, '__terraunit__', this.unitName);
await fs.mkdir(dir, { recursive: true });
for(configuration of configurations) {
const filePath = path.join(dir, configuration.fileName);
const subdir = path.dirname(filePath);
if(subdir) {
await fs.mkdir(subdir, { recursive: true });
}
await fs.appendFile(filePath, configuration.content);
files.add(filePath);
}
const debug = isDebugModeOn(this.debugMode);
const env = {
TF_LOG: debug ? 'TRACE' : '',
TF_PLUGIN_CACHE_DIR: path.join(workingDirectory, '__terraunit__', 'plugin-cache')
};
await fs.mkdir(env.TF_PLUGIN_CACHE_DIR, { recursive: true });
let result = await execa.command('terraform init', { cwd: dir, env });
if(debug && result.stdout) console.log(result.stdout);
result = await execa.command('terraform validate', { cwd: dir, env });
if(debug && result.stdout) console.log(result.stdout);
result = await execa.command('terraform plan -out _plan', { cwd: dir, env });
if(debug && result.stdout) console.log(result.stdout);
result = await execa.command('terraform show -json _plan', { cwd: dir, env });
if(debug && result.stdout) console.log(result.stdout);
files.add(path.join(dir, '_plan'));
const plan = JSON.parse(result.stdout);
return {
plan: plan,
find: (matcher) => {
const context = {};
_find(plan, matcher, context);
return context.result;
}
};
} finally {
for(file of files) {
await fs.unlink(file);
}
}
};
this._getMockAWSProvider = async (alias) => {
let template = await fs.readFile(path.join(__dirname, 'data/mock-aws-provider.template'), 'utf-8');
if(alias) {
alias = `alias = "${alias}"`;
} else {
alias = '';
}
template = template.replace(/\$\{alias\}/g, alias);
template = template.replace(/\$\{port\}/g, this.mockAws.port);
return template;
};
this._isDebugOn = () => {
let _debugMode = this.debugMode || Terraunit.DEBUG_MODE.LOCAL;
if (process.env.TERRAUNIT_DEBUG) _debugMode = process.env.TERRAUNIT_DEBUG;
if (Terraunit.DEBUG_MODE.ALL == _debugMode) return true;
if (Terraunit.DEBUG_MODE.CI == _debugMode && ci.isCI) return true;
if (Terraunit.DEBUG_MODE.LOCAL == _debugMode && !ci.isCI) return true;
return false;
}
};
const _find = (o, matcher, context) => {
if(!o) {
return;
}
if(matcher(o)) {
context.result = o;
} else if(Array.isArray(o)) {
for(i of o) {
if(typeof i === 'object') {
_find(i, matcher, context);
}
}
} else if(typeof o === 'object') {
for(key of Object.keys(o)) {
if(typeof o[key] === 'object') {
_find(o[key], matcher, context);
}
}
}
};
module.exports = Terraunit;