From 189fe015266f2a3c5bc790c80f19758d9212c2e6 Mon Sep 17 00:00:00 2001 From: Simon Li Date: Sun, 19 Nov 2023 22:25:11 +0000 Subject: [PATCH] Add diff option to deploy.py --- deploy.py | 157 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 110 insertions(+), 47 deletions(-) diff --git a/deploy.py b/deploy.py index ec8e3e5b2..9112cf00c 100755 --- a/deploy.py +++ b/deploy.py @@ -10,11 +10,12 @@ # Color codes for colored output! if os.environ.get("TERM"): BOLD = subprocess.check_output(["tput", "bold"]).decode() + RED = subprocess.check_output(["tput", "setaf", "1"]).decode() GREEN = subprocess.check_output(["tput", "setaf", "2"]).decode() NC = subprocess.check_output(["tput", "sgr0"]).decode() else: # no term, no colors - BOLD = GREEN = NC = "" + BOLD = RED = GREEN = NC = "" HERE = os.path.dirname(__file__) ABSOLUTE_HERE = os.path.dirname(os.path.realpath(__file__)) @@ -35,6 +36,8 @@ # Mapping of cluster names (keys) to resource group names (values) for Azure deployments AZURE_RGs = {} +DIFF_CONTEXT = 3 + def check_call(cmd, dry_run): """ @@ -195,7 +198,7 @@ def get_config_files(release, config_dir="config"): return config_files -def deploy(release, name=None, dry_run=False): +def deploy(release, name=None, dry_run=False, diff=False): """Deploys a federation member to a k8s cluster. Waits for deployments and daemonsets to become Ready @@ -203,17 +206,32 @@ def deploy(release, name=None, dry_run=False): if not name: name = release + if diff: + helm_commands = [ + "diff", + "--context", + str(DIFF_CONTEXT), + "upgrade", + "--install", + ] + else: + helm_commands = [ + "upgrade", + "--install", + "--cleanup-on-fail", + "--create-namespace", + ] + print(BOLD + GREEN + f"Starting helm upgrade for {release}" + NC, flush=True) - helm = [ - "helm", - "upgrade", - "--install", - "--cleanup-on-fail", - "--create-namespace", - f"--namespace={name}", - name, - "mybinder", - ] + helm = ( + ["helm"] + + helm_commands + + [ + f"--namespace={name}", + name, + "mybinder", + ] + ) config_files = get_config_files(release) # add config files to helm command @@ -222,10 +240,12 @@ def deploy(release, name=None, dry_run=False): check_call(helm, dry_run) print( - BOLD + GREEN + f"SUCCESS: Helm upgrade for {release} completed" + NC, flush=True + BOLD + GREEN + f"SUCCESS: Helm {helm_commands[0]} for {release} completed" + NC, + flush=True, ) - wait_for_deployments_daemonsets(name, dry_run) + if not diff: + wait_for_deployments_daemonsets(name, dry_run) def wait_for_deployments_daemonsets(name, dry_run=False): @@ -269,7 +289,7 @@ def wait_for_deployments_daemonsets(name, dry_run=False): ) -def setup_certmanager(dry_run=False): +def setup_certmanager(dry_run=False, diff=False): """ Install cert-manager separately into its own namespace and `kubectl apply` its CRDs each time as helm won't attempt to handle changes to CRD resources. @@ -286,32 +306,52 @@ def setup_certmanager(dry_run=False): manifest_url = f"https://github.com/jetstack/cert-manager/releases/download/{version}/cert-manager.crds.yaml" print(BOLD + GREEN + f"Installing cert-manager CRDs {version}" + NC, flush=True) + if diff: + kubectl_commands = ["diff"] + helm_commands = [ + "diff", + "--context", + str(DIFF_CONTEXT), + "upgrade", + "--install", + ] + else: + kubectl_commands = ["apply"] + helm_commands = [ + "upgrade", + "--install", + "--create-namespace", + ] + # Sometimes 'replace' is needed for upgrade (e.g. 1.1->1.2) - check_call(["kubectl", "apply", "-f", manifest_url], dry_run) + check_call(["kubectl"] + kubectl_commands + ["-f", manifest_url], dry_run) print(BOLD + GREEN + f"Installing cert-manager {version}" + NC, flush=True) - helm_upgrade = [ - "helm", - "upgrade", - "--install", - "--create-namespace", - "--namespace=cert-manager", - "--repo=https://charts.jetstack.io", - "cert-manager", - "cert-manager", - f"--version={version}", - "--values=config/cert-manager.yaml", - ] + helm_upgrade = ( + ["helm"] + + helm_commands + + [ + "--namespace=cert-manager", + "--repo=https://charts.jetstack.io", + "cert-manager", + "cert-manager", + f"--version={version}", + "--values=config/cert-manager.yaml", + ] + ) check_call(helm_upgrade, dry_run) -def patch_coredns(dry_run=False): +def patch_coredns(dry_run=False, diff=False): """Patch coredns resource allocation OVH2 coredns does not have sufficient memory by default after our ban patches """ print(BOLD + GREEN + "Patching coredns resources" + NC, flush=True) + if diff: + print(BOLD + RED + "diff not supported" + NC, flush=True) + return check_call( [ "kubectl", @@ -329,7 +369,7 @@ def patch_coredns(dry_run=False): ) -def deploy_system_charts(release, name=None, dry_run=False): +def deploy_system_charts(release, name=None, dry_run=False, diff=False): """ Some charts must be deployed into other namespaces """ @@ -350,26 +390,44 @@ def deploy_system_charts(release, name=None, dry_run=False): return print(BOLD + GREEN + f"Starting helm upgrade for {log_name}" + NC, flush=True) - helm = [ - "helm", - "upgrade", - "--install", - "--cleanup-on-fail", - f"--namespace={ns}", - "--create-namespace", - name, - chart, - ] + if diff: + helm_commands = [ + "diff", + "--context", + str(DIFF_CONTEXT), + "upgrade", + "--install", + ] + else: + helm_commands = [ + "upgrade", + "--install", + "--create-namespace", + "--cleanup-on-fail", + ] + helm = ( + ["helm"] + + helm_commands + + [ + f"--namespace={ns}", + name, + chart, + ] + ) for config_file in config_files: helm.extend(["-f", config_file]) check_call(helm, dry_run) print( - BOLD + GREEN + f"SUCCESS: Helm upgrade for {log_name} completed" + NC, + BOLD + + GREEN + + f"SUCCESS: Helm {helm_commands[0]} for {log_name} completed" + + NC, flush=True, ) - wait_for_deployments_daemonsets(ns, dry_run) + if not diff: + wait_for_deployments_daemonsets(ns, dry_run) def main(): @@ -406,6 +464,11 @@ def main(): action="store_true", help="Print commands, but don't run them", ) + argparser.add_argument( + "--diff", + action="store_true", + help="Run helm/kubectl diff (plugins must be installed), do not make any changes", + ) stages = ["all", "auth", "networkban", "system", "certmanager", "mybinder"] argparser.add_argument( "--stage", @@ -450,7 +513,7 @@ def main(): if args.stage in ("all", "auth"): if cluster.startswith("ovh"): setup_auth_ovh(args.release, cluster, args.dry_run) - patch_coredns(args.dry_run) + patch_coredns(args.dry_run, args.diff) elif cluster in AZURE_RGs: setup_auth_azure(cluster, args.dry_run) elif cluster in GCP_PROJECTS: @@ -461,13 +524,13 @@ def main(): raise Exception("Cloud cluster not recognised!") if args.stage in ("all", "networkban"): - update_networkbans(cluster, args.dry_run) + update_networkbans(cluster, args.dry_run, args.diff) if args.stage in ("all", "system"): - deploy_system_charts(args.release, args.name, args.dry_run) + deploy_system_charts(args.release, args.name, args.dry_run, args.diff) if args.stage in ("all", "certmanager"): - setup_certmanager(args.dry_run) + setup_certmanager(args.dry_run, args.diff) if args.stage in ("all", "mybinder"): - deploy(args.release, args.name, args.dry_run) + deploy(args.release, args.name, args.dry_run, args.diff) if __name__ == "__main__":