-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy path.dodo.py.template
213 lines (183 loc) · 7.12 KB
/
.dodo.py.template
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import os
import uuid
import sys
import zipfile
from datetime import date, timedelta
from pathlib import *
from hx.dodo_helpers import MarkerFile, DockerContext, DockerImage, rglobfiles, YarnNodeModules, fileAge
from hx.dodo_infrastructure import run_dockerized_terraform, update_camus2, lambdazip_file_task, lambdazip_pydir_task
# Use helix's packaged terraform and associated tools
# from the image helixta/terraform at this version:
TERRAFORM_IMAGE = 'helixta/terraform:2019-03-11'
HERE = Path('.')
es_tool_build_file = (HERE/'typescript/build/hx-terraform/tools/es-tool.js')
provisioning_tools = HERE / 'generate/.stack-work/install/x86_64-linux/lts-10.10/8.2.2/bin/hx-provisioning-tools'
local_lambda_zip_sources = HERE/'lambdas'
lambda_zip_sources = HERE/'typescript/hx-terraform/aws/lambdas'
lambda_es_tool = HERE/'typescript/build/hx-terraform/tools/es-tool.js'
lambda_source_files = (list(local_lambda_zip_sources.glob("*")) + list(lambda_zip_sources.glob("*")) + [ lambda_es_tool ])
tfplan = HERE / 'terraform/tfplan'
# These are actually symlinked so they share package.json
nodemodules = YarnNodeModules(HERE / 'typescript')
hxtnodemodules = YarnNodeModules(HERE / 'typescript'/'hx-terraform')
def dockerized_terraform(cmd):
return run_dockerized_terraform(TERRAFORM_IMAGE, cmd)
def task_node_modules():
yield nodemodules.task()
yield hxtnodemodules.task()
def generate_providers():
return '(cd typescript; ./node_modules/.bin/ts-node hx-terraform/tools/gen-providers.ts)'
def generate_tf():
return '(cd typescript; ./node_modules/.bin/ts-node main.ts)'
def yarn_build():
return '(cd typescript; yarn build)'
def confirm_apply():
print("You are about to apply changes to live infrastructure.")
print("Please confirm you have checked the plan and wish to proceed")
print("by entering yes: ", end='')
s = input().strip()
if s != "yes":
print("terraform apply aborted")
sys.exit(1)
def check_plan():
""" Ensure the plan is not too old """
if not tfplan.exists():
print("Error - no plan file found - Run 'doit plan' first.")
exit(1)
ageThresholdSeconds = 2 * 60
if fileAge(tfplan) > ageThresholdSeconds:
print("Plan has expired - please try again.")
expire_plan()
exit(1)
def expire_plan():
tfplan.unlink()
def task_lambda_zips():
# Required for compiling typescript
yield {
'name': 'yarn build',
'actions': [ yarn_build() ],
'targets': [ es_tool_build_file ],
'file_dep': [ (HERE/'typescript/hx-terraform/tools/es-tool.ts') ]
}
for f in lambda_source_files:
zipfile = (HERE/'build/lambdas/'/f.stem).with_suffix('.zip')
if f.suffix == '.py':
yield lambdazip_file_task(zipfile, f)
elif f.suffix == '.js':
yield {
**lambdazip_file_task(zipfile, f),
'file_dep': [ es_tool_build_file ],
}
elif f.is_dir() and (f/'requirements.txt').is_file():
yield lambdazip_pydir_task(zipfile, f)
def task_generate_providers():
return {
'doc' : 'Generate typescript for providers',
'actions' : [generate_providers()],
'file_dep': [
HERE/'typescript/hx-terraform/tools/gen-helpers.ts',
HERE/'typescript/hx-terraform/tools/gen-providers.ts'] +
[f for f in rglobfiles(HERE/'typescript/hx-terraform/providers') if not f.name == 'resources.ts'] +
nodemodules.file_dep() +
hxtnodemodules.file_dep(),
'targets': [
HERE/'typescript/hx-terraform/providers/aws/resources.ts',
HERE/'typescript/hx-terraform/providers/random/resources.ts',
]
}
def task_generate_terraform():
return {
'doc' : 'Generate terraform files from the terraform EDSL',
'actions' : [
generate_tf()
],
'task_dep': ['generate_providers'],
'file_dep': [f for f in rglobfiles(HERE/'typescript') if not 'node_modules' in f.parts] +
nodemodules.file_dep() +
hxtnodemodules.file_dep(),
'targets': [
HERE/'terraform'/'.manifest.adhoc',
HERE/'terraform'/'.manifest.backend',
HERE/'terraform'/'.manifest.providers',
HERE/'terraform'/'.manifest.resources'
],
'verbosity':2
}
def task_generate():
return {
'doc' : '(alias of generate_terraform)',
'task_dep': ['generate_terraform'],
'actions': [],
'uptodate': [False],
}
def task_terraform_init():
return {
'doc' : '(Re)Initialize terraform on initial setup and/or changes to backend/provider',
'actions': [ dockerized_terraform(['init', '--force-copy']) ],
'file_dep': [
HERE/'terraform'/'.manifest.backend',
HERE/'terraform'/'.manifest.providers'
],
'verbosity' : 2
}
def task_plan():
return {
'doc' : 'Execute terraform plan to show pending infrastructure changes and save the plan',
'actions': [
dockerized_terraform(['plan', '-parallelism=20', '-out=tfplan']) +
"| grep --line-buffered -v 'This plan was saved to'" +
"| grep --line-buffered -v 'To perform exactly these actions'" +
"| grep --line-buffered -v 'terraform apply'",
'echo "Review the above plan and run:\n doit apply"'
],
'task_dep': [ 'terraform_init', ],
'file_dep':
lambda_zipfiles() +
[
HERE/'terraform'/'.manifest.adhoc',
HERE/'terraform'/'.manifest.backend',
HERE/'terraform'/'.manifest.providers',
HERE/'terraform'/'.manifest.resources'
] +
[ f for f in rglobfiles(HERE/"terraform") if f.name != 'tfplan' and '.terraform' not in f.parts ],
'targets': [
HERE/"terraform/tfplan"
],
'verbosity' : 2,
'uptodate': [False] # always run
}
def task_apply():
return {
'doc' : 'Execute terraform apply to make any pending infrastructure changes according to the plan',
'actions': [
check_plan,
confirm_apply,
dockerized_terraform(['apply', 'tfplan']),
expire_plan # invalidate the plan after using it
],
'file_dep': lambda_zipfiles(), # no doit dependency back into tfplan - you have to run "doit plan" explicitly
'verbosity' : 2,
'uptodate': [False],
}
def task_refresh():
return {
'doc' : 'Run terraform refresh to update state from current deployed resources',
'actions': [ dockerized_terraform(['refresh']) ],
'verbosity' : 2,
'uptodate': [False],
}
def task_output():
return {
'doc' : 'Run terraform to show terraform outputs',
'actions': [ dockerized_terraform(['output']) ],
'verbosity' : 2,
'uptodate': [False],
}
def task_update_camus2():
return update_camus2(HERE)
def lambda_zipfiles():
zipfiles = []
for f in lambda_source_files:
zipfile = (HERE/'build/lambdas/'/f.stem).with_suffix('.zip')
zipfiles.append(zipfile)
return zipfiles