diff --git a/docs/upgrading.rst b/docs/upgrading.rst index fed8c7e95a887d6bf9acdac6df155c8035b8e928..091b9fafe2a468398432e88b6aca4e6f2df0846f 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -58,7 +58,8 @@ these applications form the script manually. # Execute the upgrade preparation script ./rename-to-stackspin.sh -After this, you need to manually re-install the applications by running +After this, you need to update secrets and Flux in the cluster by running +``install/install-stackspin.sh``. Then re-install applications by running ``install/install-app.sh <app>`` from the Stackspin repository. See the application specific upgrade guides below. diff --git a/install/generate_secrets.py b/install/generate_secrets.py index bf6cf0e013fa225ba6afb3c40e1690c64c8b33b9..6ff53ac011cc29c9e4142f3d15812ffff1f9a27c 100644 --- a/install/generate_secrets.py +++ b/install/generate_secrets.py @@ -56,14 +56,17 @@ def create_variables_secret(app_name, env): with open(variables_filename) as template_file: lines = template_file.read() secret_name, secret_namespace = get_secret_metadata(lines) - if get_kubernetes_secret(secret_name, secret_namespace) is None: - print(f"Adding secret {secret_name} in namespace" - f" {secret_namespace} to cluster.") - template = env.from_string(lines) - store_kubernetes_secret(template.render(), secret_namespace) - else: + new_secret_dict = yaml.safe_load(env.from_string(lines).render()) + current_secret_data = get_kubernetes_secret_data(secret_name, + secret_namespace) + if current_secret_data is not None: print(f"Secret {secret_name} in namespace {secret_namespace}" - " already exists. Not generating new secrets.") + " already exists. Merging...") + # Merge dicts. Values from current_secret_data take precedence + new_secret_dict['data'] |= current_secret_data + print(f"Storing secret {secret_name} in namespace" + f" {secret_namespace} in cluster.") + store_kubernetes_secret(new_secret_dict, secret_namespace) else: print(f'File {variables_filename} does not exist.') @@ -77,7 +80,7 @@ def create_basic_auth_secret(app_name, env): lines = template_file.read() secret_name, secret_namespace = get_secret_metadata(lines) - if get_kubernetes_secret(secret_name, secret_namespace) is None: + if get_kubernetes_secret_data(secret_name, secret_namespace) is None: basic_auth_username = 'admin' basic_auth_password = generate_password(32) basic_auth_htpasswd = gen_htpasswd( @@ -91,7 +94,8 @@ def create_basic_auth_secret(app_name, env): 'pass': basic_auth_password, 'htpasswd': basic_auth_htpasswd }) - store_kubernetes_secret(template.render(), secret_namespace) + secret_dict = yaml.safe_load(template.render()) + store_kubernetes_secret(secret_dict, secret_namespace) else: print(f"Secret {secret_name} in namespace {secret_namespace}" " already exists. Not generating new secrets.") @@ -100,18 +104,18 @@ def create_basic_auth_secret(app_name, env): def get_secret_metadata(yaml_string): """Returns secret name and namespace from metadata field in a yaml string""" - secret_info = yaml.safe_load(yaml_string) - secret_name = secret_info['metadata']['name'] + secret_dict = yaml.safe_load(yaml_string) + secret_name = secret_dict['metadata']['name'] # default namespace is flux-system, but other namespace can be # provided in secret metadata - if 'namespace' in secret_info['metadata']: - secret_namespace = secret_info['metadata']['namespace'] + if 'namespace' in secret_dict['metadata']: + secret_namespace = secret_dict['metadata']['namespace'] else: secret_namespace = 'flux-system' return secret_name, secret_namespace -def get_kubernetes_secret(secret_name, namespace): +def get_kubernetes_secret_data(secret_name, namespace): """Returns the contents of a kubernetes secret or None if the secret does not exist.""" try: secret = API.read_namespaced_secret(secret_name, namespace).data @@ -122,13 +126,12 @@ def get_kubernetes_secret(secret_name, namespace): return None return secret -def store_kubernetes_secret(secret_string, namespace): +def store_kubernetes_secret(secret_dict, namespace): """Converts secret_string into a yaml object and adds it to the cluster""" - secret_yaml = yaml.safe_load(secret_string) api_client = client.api_client.ApiClient() api_response = create_from_yaml( api_client, - yaml_objects=[secret_yaml], + yaml_objects=[secret_dict], namespace=namespace) print(f"Secret created with api response: {api_response}")