Skip to content

Commit a09e6ed

Browse files
authored
Merge pull request jupyterhub#2671 from manics/deploy-dryrun
`deploy.py`: add dry-run option + minor refactor to support future deployments
2 parents 6b674c5 + 863b24a commit a09e6ed

File tree

1 file changed

+77
-39
lines changed

1 file changed

+77
-39
lines changed

deploy.py

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,30 @@
3333
AZURE_RGs = {}
3434

3535

36-
def setup_auth_azure(cluster):
36+
def check_call(cmd, dry_run):
37+
"""
38+
Print a command if dry_run is true, otherwise run it with subprocess.check_call
39+
"""
40+
if dry_run:
41+
print("dry-run:", " ".join(cmd))
42+
else:
43+
subprocess.check_call(cmd)
44+
45+
46+
def check_output(cmd, dry_run):
47+
"""
48+
Print a command if dry_run is true, otherwise run it with subprocess.check_output
49+
and return decoded output
50+
"""
51+
if dry_run:
52+
print("dry-run:", " ".join(cmd))
53+
return ""
54+
else:
55+
out = subprocess.check_output(cmd)
56+
return out.decode("utf-8")
57+
58+
59+
def setup_auth_azure(cluster, dry_run=False):
3760
"""
3861
Set up authentication with a k8s cluster on Azure.
3962
"""
@@ -55,7 +78,7 @@ def setup_auth_azure(cluster):
5578
"--tenant",
5679
azure["tenant-id"],
5780
]
58-
subprocess.check_output(login_cmd)
81+
check_output(login_cmd, dry_run)
5982

6083
# Set kubeconfig
6184
creds_cmd = [
@@ -67,11 +90,11 @@ def setup_auth_azure(cluster):
6790
"--resource-group",
6891
AZURE_RGs[cluster],
6992
]
70-
stdout = subprocess.check_output(creds_cmd)
71-
print(stdout.decode("utf-8"))
93+
stdout = check_output(creds_cmd, dry_run)
94+
print(stdout)
7295

7396

74-
def setup_auth_ovh(release, cluster):
97+
def setup_auth_ovh(release, cluster, dry_run=False):
7598
"""
7699
Set up authentication with 'ovh' K8S from the ovh-kubeconfig.yml
77100
"""
@@ -80,29 +103,30 @@ def setup_auth_ovh(release, cluster):
80103
ovh_kubeconfig = os.path.join(ABSOLUTE_HERE, "secrets", f"{release}-kubeconfig.yml")
81104
os.environ["KUBECONFIG"] = ovh_kubeconfig
82105
print(f"Current KUBECONFIG='{ovh_kubeconfig}'")
83-
stdout = subprocess.check_output(["kubectl", "config", "use-context", cluster])
84-
print(stdout.decode("utf8"))
106+
stdout = check_output(["kubectl", "config", "use-context", cluster], dry_run)
107+
print(stdout)
85108

86109

87-
def setup_auth_gcloud(release, cluster=None):
110+
def setup_auth_gcloud(release, cluster=None, dry_run=False):
88111
"""
89112
Set up GCloud + Kubectl authentication for talking to a given cluster
90113
"""
91114
# Authenticate to GoogleCloud using a service account
92-
subprocess.check_output(
115+
check_output(
93116
[
94117
"gcloud",
95118
"auth",
96119
"activate-service-account",
97120
f"--key-file=secrets/gke-auth-key-{release}.json",
98-
]
121+
],
122+
dry_run,
99123
)
100124

101125
project = GCP_PROJECTS[release]
102126
zone = GCP_ZONES[release]
103127

104128
# Use gcloud to populate ~/.kube/config, which kubectl / helm can use
105-
subprocess.check_call(
129+
check_call(
106130
[
107131
"gcloud",
108132
"container",
@@ -111,11 +135,12 @@ def setup_auth_gcloud(release, cluster=None):
111135
cluster,
112136
f"--zone={zone}",
113137
f"--project={project}",
114-
]
138+
],
139+
dry_run,
115140
)
116141

117142

118-
def update_networkbans(cluster):
143+
def update_networkbans(cluster, dry_run=False):
119144
"""
120145
Run secrets/ban.py to update network bans
121146
"""
@@ -128,23 +153,23 @@ def update_networkbans(cluster):
128153
if cluster in {"ovh", "ovh2"}:
129154
ban_command.append(cluster)
130155

131-
subprocess.check_call(ban_command)
156+
check_call(ban_command, dry_run)
132157

133158

134-
def get_config_files(release):
159+
def get_config_files(release, config_dir="config"):
135160
"""Return the list of config files to load"""
136161
# common config files
137-
config_files = sorted(glob.glob(os.path.join("config", "common", "*.yaml")))
162+
config_files = sorted(glob.glob(os.path.join(config_dir, "common", "*.yaml")))
138163
config_files.extend(
139-
sorted(glob.glob(os.path.join("secrets", "config", "common", "*.yaml")))
164+
sorted(glob.glob(os.path.join("secrets", config_dir, "common", "*.yaml")))
140165
)
141166
# release-specific config files
142-
for config_dir in ("config", "secrets/config"):
167+
for config_dir in (config_dir, os.path.join("secrets", config_dir)):
143168
config_files.append(os.path.join(config_dir, release + ".yaml"))
144169
return config_files
145170

146171

147-
def deploy(release, name=None):
172+
def deploy(release, name=None, dry_run=False):
148173
"""Deploys a federation member to a k8s cluster.
149174
150175
The deployment is done in the following steps:
@@ -156,7 +181,7 @@ def deploy(release, name=None):
156181
if not name:
157182
name = release
158183

159-
setup_certmanager()
184+
setup_certmanager(dry_run)
160185

161186
print(BOLD + GREEN + f"Starting helm upgrade for {release}" + NC, flush=True)
162187
helm = [
@@ -175,12 +200,18 @@ def deploy(release, name=None):
175200
for config_file in config_files:
176201
helm.extend(["-f", config_file])
177202

178-
subprocess.check_call(helm)
203+
check_call(helm, dry_run)
179204
print(
180205
BOLD + GREEN + f"SUCCESS: Helm upgrade for {release} completed" + NC, flush=True
181206
)
182207

183-
# Explicitly wait for all deployments and daemonsets to be fully rolled out
208+
wait_for_deployments_daemonsets(name, dry_run)
209+
210+
211+
def wait_for_deployments_daemonsets(name, dry_run=False):
212+
"""
213+
Wait for all deployments and daemonsets to be fully rolled out
214+
"""
184215
print(
185216
BOLD
186217
+ GREEN
@@ -189,22 +220,22 @@ def deploy(release, name=None):
189220
flush=True,
190221
)
191222
deployments_and_daemonsets = (
192-
subprocess.check_output(
223+
check_output(
193224
[
194225
"kubectl",
195226
"get",
196227
f"--namespace={name}",
197228
"--output=name",
198229
"deployments,daemonsets",
199-
]
230+
],
231+
dry_run,
200232
)
201-
.decode()
202233
.strip()
203234
.split("\n")
204235
)
205236

206237
for d in deployments_and_daemonsets:
207-
subprocess.check_call(
238+
check_call(
208239
[
209240
"kubectl",
210241
"rollout",
@@ -213,11 +244,12 @@ def deploy(release, name=None):
213244
"--timeout=10m",
214245
"--watch",
215246
d,
216-
]
247+
],
248+
dry_run,
217249
)
218250

219251

220-
def setup_certmanager():
252+
def setup_certmanager(dry_run=False):
221253
"""
222254
Install cert-manager separately into its own namespace and `kubectl apply`
223255
its CRDs each time as helm won't attempt to handle changes to CRD resources.
@@ -235,7 +267,7 @@ def setup_certmanager():
235267
print(BOLD + GREEN + f"Installing cert-manager CRDs {version}" + NC, flush=True)
236268

237269
# Sometimes 'replace' is needed for upgrade (e.g. 1.1->1.2)
238-
subprocess.check_call(["kubectl", "apply", "-f", manifest_url])
270+
check_call(["kubectl", "apply", "-f", manifest_url], dry_run)
239271

240272
print(BOLD + GREEN + f"Installing cert-manager {version}" + NC, flush=True)
241273
helm_upgrade = [
@@ -251,16 +283,16 @@ def setup_certmanager():
251283
"--values=config/cert-manager.yaml",
252284
]
253285

254-
subprocess.check_call(helm_upgrade)
286+
check_call(helm_upgrade, dry_run)
255287

256288

257-
def patch_coredns():
289+
def patch_coredns(dry_run=False):
258290
"""Patch coredns resource allocation
259291
260292
OVH2 coredns does not have sufficient memory by default after our ban patches
261293
"""
262294
print(BOLD + GREEN + "Patching coredns resources" + NC, flush=True)
263-
subprocess.check_call(
295+
check_call(
264296
[
265297
"kubectl",
266298
"set",
@@ -272,7 +304,8 @@ def patch_coredns():
272304
"memory=250Mi",
273305
"--requests",
274306
"memory=200Mi",
275-
]
307+
],
308+
dry_run,
276309
)
277310

278311

@@ -304,6 +337,11 @@ def main():
304337
action="store_true",
305338
help="If the script is running locally, skip auth step",
306339
)
340+
argparser.add_argument(
341+
"--dry-run",
342+
action="store_true",
343+
help="Print commands, but don't run them",
344+
)
307345

308346
args = argparser.parse_args()
309347

@@ -339,17 +377,17 @@ def main():
339377
# script is running on CI, proceed with auth and helm setup
340378

341379
if cluster.startswith("ovh"):
342-
setup_auth_ovh(args.release, cluster)
343-
patch_coredns()
380+
setup_auth_ovh(args.release, cluster, args.dry_run)
381+
patch_coredns(args.dry_run)
344382
elif cluster in AZURE_RGs:
345-
setup_auth_azure(cluster)
383+
setup_auth_azure(cluster, args.dry_run)
346384
elif cluster in GCP_PROJECTS:
347-
setup_auth_gcloud(args.release, cluster)
385+
setup_auth_gcloud(args.release, cluster, args.dry_run)
348386
else:
349387
raise Exception("Cloud cluster not recognised!")
350388

351-
update_networkbans(cluster)
352-
deploy(args.release, args.name)
389+
update_networkbans(cluster, args.dry_run)
390+
deploy(args.release, args.name, args.dry_run)
353391

354392

355393
if __name__ == "__main__":

0 commit comments

Comments
 (0)