diff --git a/controllerconfig/controllerconfig/scripts/migrate_helm_release.py b/controllerconfig/controllerconfig/scripts/migrate_helm_release.py deleted file mode 100644 index 501f15f9c5..0000000000 --- a/controllerconfig/controllerconfig/scripts/migrate_helm_release.py +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# This script will perform helm v2 to helm v3 resource migration. This includes -# using the helm 2to3 plugin along with labeling and annotating cluster -# resources associated with the helm release so that it is managable by helm v3 -# - -import keyring -import psycopg2 -import subprocess -import sys -import os - -from controllerconfig.common import log -from psycopg2.extras import RealDictCursor -LOG = log.get_logger(__name__) - - -def main(): - if len(sys.argv) != 2: - raise Exception("Release name should be specified") - - log.configure() - - release = sys.argv[1] - LOG.info("Starting to migrate release {}".format(release)) - conn = init_connection() - migrate_release(conn, release) - - -def init_connection(): - helmv2_db_pw = keyring.get_password("helmv2", "database") - if not helmv2_db_pw: - raise Exception("Unable to get password to access helmv2 database.") - - return psycopg2.connect(user="admin-helmv2", - password=helmv2_db_pw, - host="localhost", - database="helmv2") - - -def migrate_release(conn, release): - release_info = get_release_info(conn, release) - release_name = release_info["name"] - create_configmap(release_info) - helm2to3_migrate(release_name) - update_release_resources(release_name) - cleanup_release(conn, release_name) - - -def get_release_info(conn, release): - release_info = None - with conn: - with conn.cursor(cursor_factory=RealDictCursor) as cur: - cur.execute("select * from releases where name = %s", (release,)) - release_info = cur.fetchone() - if not release_info: - raise Exception("Release name is not present in the DB") - return release_info - - -def create_configmap(release_info): - configmap_label_name = release_info["name"] - configmap = """ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {key} - namespace: kube-system - labels: - NAME: {name} - STATUS: {status} - OWNER: {owner} - VERSION: "{version}" -data: - release: {release} -""".format(key=release_info["key"], - name=configmap_label_name, - status=release_info["status"], - owner=release_info["owner"], - version=release_info["version"], - release=release_info["body"]) - - configmap_path = os.path.join("/tmp", configmap_label_name + ".yaml") - with open(configmap_path, "w") as f: - f.write(configmap) - - cmd = "kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f {}" \ - .format(configmap_path) - execute_command(cmd) - LOG.info("Configmap {} created".format(configmap_label_name)) - os.remove(configmap_path) - - -def helm2to3_migrate(release_name): - cmd = ("helm 2to3 convert --kubeconfig=/etc/kubernetes/admin.conf " - "--tiller-out-cluster -s configmaps {}".format(release_name)) - execute_command(cmd) - LOG.info("Migrated {} helm2 release to helm3".format(release_name)) - - -def get_api_resources(namespaced=True): - if namespaced: - namespace_arg = ' --namespaced=true' - else: - namespace_arg = ' --namespaced=false' - - # Get all API resources - try: - api_resources = [] - api_resources_query = subprocess.check_output( - ("kubectl --kubeconfig=/etc/kubernetes/admin.conf api-resources " - " --verbs=list {} -o name".format(namespace_arg)), - shell=True, stderr=subprocess.STDOUT).decode('utf-8') - if api_resources_query: - api_resources = [a for a in api_resources_query.split("\n") if a] - except Exception as e: - LOG.info("Exception {} occured when trying to get kubernetes API " - "resources".format(e)) - raise - return api_resources - - -def update_release_resources(release_name): - """ Properly label resources to support Helm v3 - - Per https://github.com/helm/helm-2to3/issues/147, existing cluster - resources deployed by helm v2 are not labeled properly for helm v3. - Search for deployed resources based on release name and adjust the - labeling. - """ - - LOG.info("Gathering namespaced kubernetes API resources...") - namespaced_api_resources = get_api_resources(namespaced=True) - - LOG.info("Gathering non-namespaced kubernetes API resources...") - nonamespaced_api_resources = get_api_resources(namespaced=False) - - # Get all helm release resources - release_resources = [] - for r in namespaced_api_resources + nonamespaced_api_resources: - if r in nonamespaced_api_resources: - awk_print = '{print $1}' - else: - awk_print = '{print "-n "$1" "$2}' - - LOG.info("Searching for {} resource related to {}...".format( - r, release_name)) - try: - cmd = ("kubectl --kubeconfig=/etc/kubernetes/admin.conf get -A " - "-l app.kubernetes.io/instance={} --show-kind " - "--ignore-not-found --no-headers {}".format( - release_name, r)) - release_query = subprocess.Popen(cmd, shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - - output_filter = subprocess.Popen(['awk', awk_print], - stdin=release_query.stdout, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - release_query.stdout.close() - resource_list, err = output_filter.communicate() - if output_filter.returncode != 0: - LOG.info("Command failed:\n {}\n{}\n{}".format( - cmd, resource_list, err)) - raise Exception("Failed to execute command: %s" % cmd) - - if resource_list: - resources = [r for r in resource_list.split("\n") if r] - release_resources += resources - - except Exception as e: - LOG.info("Exception {} occured when trying to check for {} use of " - "API resource {}".format(e, release_name, r)) - continue - - # Dump the resources need to be labeled/annotated - for r in release_resources: - LOG.info("Found {} resource: {}".format(release_name, r)) - - # Label the resources appropriately to support the release upgrade - for tiller_managed_resource in release_resources: - try: - labeling_out = subprocess.check_output( - ('kubectl --kubeconfig=/etc/kubernetes/admin.conf label ' - '--overwrite {} ' - '"app.kubernetes.io/managed-by=Helm"'.format( - tiller_managed_resource)), - shell=True, stderr=subprocess.STDOUT).decode('utf-8') - LOG.info(labeling_out) - except Exception as e: - LOG.info("Exception {} occured when trying to label '{}'".format( - e, tiller_managed_resource)) - continue - - if "-n " in tiller_managed_resource: - # Extract and annotate the namespaced resource - # Ex: '-n metrics-server deployment.apps/ms-metrics-server' - components = [c for c in tiller_managed_resource.split(" ") if c] - namespace = components[1] - - try: - annotate_out = subprocess.check_output( - ('kubectl --kubeconfig=/etc/kubernetes/admin.conf annotate' - ' --overwrite {} "meta.helm.sh/release-name={}" ' - '"meta.helm.sh/release-namespace={}"'.format( - tiller_managed_resource, release_name, namespace)), - shell=True, stderr=subprocess.STDOUT).decode('utf-8') - LOG.info(annotate_out) - except Exception as e: - LOG.info("Exception {} occured when trying to annotate " - "'{}'".format(e, tiller_managed_resource)) - continue - - -def cleanup_release(conn, release_name): - cmd = ("helm 2to3 cleanup --kubeconfig=/etc/kubernetes/admin.conf " - "--release-cleanup --tiller-out-cluster -s configmaps " - "--skip-confirmation --name {}".format(release_name)) - execute_command(cmd) - with conn: - with conn.cursor() as cur: - cur.execute("delete from releases where name = %s", - (release_name,)) - - LOG.info("Cleaned up helm2 data for {}".format(release_name)) - - -def execute_command(cmd): - sub = subprocess.Popen(cmd, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - stdout, stderr = sub.communicate() - if sub.returncode != 0: - LOG.info("Command failed:\n %s\n%s\n%s" % (cmd, stdout, stderr)) - raise Exception("Failed to execute command: %s" % cmd) - return stdout - - -if __name__ == "__main__": - main() diff --git a/controllerconfig/controllerconfig/upgrade-scripts/63-helm-v2-to-v3-rel_migration.sh b/controllerconfig/controllerconfig/upgrade-scripts/63-helm-v2-to-v3-rel_migration.sh deleted file mode 100755 index 745c897d81..0000000000 --- a/controllerconfig/controllerconfig/upgrade-scripts/63-helm-v2-to-v3-rel_migration.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash -# vim: tabstop=4 shiftwidth=4 expandtab -# -# Copyright (c) 2020-2023 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# This migration script is used for migrating helmV2 applications helmrelease to -# helmV3, therefore this enables armada apps to be upgrade to FluxCD apps in a -# platform upgrade: It will: -# - Install helm-2to3 plugin -# - Move helm2 config to helm3 -# - Run migration script for each release - -set -ef - -NAME=$(basename $0) - -# The migration scripts are passed these parameters: -FROM_RELEASE=$1 -TO_RELEASE=$2 -ACTION=$3 - -PATH=$PATH:/usr/local/sbin:/usr/bin - -# This will log to /var/log/platform.log -function log { - logger -p local1.info $1 -} - -function install_helm_2to3 { - log "$NAME: Installing helm 2to3 plugin" - if ! helm plugin list | grep 2to3; then - export HELM_LINTER_PLUGIN_NO_INSTALL_HOOK=true - helm plugin install /usr/local/share/helm/plugins/2to3 - else - log "$NAME: helm 2to3 already present" - fi -} - -function get_helmv2_config { - log "$NAME: Retreiving helm config from Armada's tiller container." - JSONPATH='{range .items[*]}{"\n"}{@.metadata.name}:{@.metadata.deletionTimestamp}{range @.status.conditions[*]}{":"}{@.type}={@.status}{end}{end}' - ARMADA_PODS=( $(kubectl get pods -n armada \ - --kubeconfig=/etc/kubernetes/admin.conf \ - --selector=application=armada,component=api \ - --field-selector status.phase=Running \ - --output=jsonpath="${JSONPATH}") ) - if [ ${#ARMADA_PODS[@]} -eq 0 ]; then - log "$NAME: ERROR - Could not find armada pod." - exit 1 - fi - - # Get first available Running and Ready armada pod, with tiller container - POD="" - for LINE in "${ARMADA_PODS[@]}"; do - # match only Ready pods with nil deletionTimestamp - if [[ $LINE =~ ::.*Ready=True ]]; then - # extract pod name, it is first element delimited by : - A=$( cut -d ':' -f 1 - <<< "${LINE}" ) - P=${A[0]} - else - continue - fi - kubectl --kubeconfig=/etc/kubernetes/admin.conf \ - cp armada/${P}:tmp/.helm "$HOME"/.helm -c tiller - RC=$? - if [ ${RC} -eq 0 ]; then - log "$NAME: helmv2 config copied to /home/sysadmin/.helm" - break - else - log "$NAME: ERROR - failed to copy helm config from helmv2 (tiller) to host. (RETURNED: $RC)" - exit 1 - fi - done - - yes | helm 2to3 move config - RC=$? - if [ ${RC} -eq 0 ]; then - log "$NAME: helmV2 release info and config moved to helmv3" - else - log "$NAME: ERROR - failed to migrate release info to helmv3. (RETURNED: $RC)" - exit 1 - fi -} - -function migrate_apps { - log "$NAME: Migrating helm releases" - HELM_REL=$(KUBECONFIG=/etc/kubernetes/admin.conf helmv2-cli -- helm list -a | tail -n+2 | awk '{print $1}') - for rel in ${HELM_REL}; do - case $rel in - # SUPPORTED: auditd-1.0-20.tgz -> 65-k8s-app-upgrade.sh - ns-auditd) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release.py $rel - ;; - # SPECIAL HANDLE: cert-manager-1.0-26.tgz -> 64-upgrade-cert-manager.sh - cm-cert-manager | cm-cert-manager-psp-rolebinding) - log "$NAME: helm release $rel is being migrated with a dedicated upgrade script." - ;; - # SUPPORTED: metrics-server-1.0-8.tgz -> 65-k8s-app-upgrade.sh - ms-metrics-server-psp-rolebinding | ms-metrics-server) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release.py $rel - ;; - # SUPPORTED: nginx-ingress-controller-1.1-18.tgz -> 65-k8s-app-upgrade.sh - ic-nginx-ingress ) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release.py $rel - ;; - # SPECIAL HANDLE: oidc-auth-apps-1.0-61.tgz -> 82-upgrade-oidc.py - oidc-dex | oidc-oidc-client | oidc-auth-secret-observer) - log "$NAME: helm release $rel is being migrated with a dedicated upgrade script." - ;; - # SUPPORTED: platform-integ-apps-1.0-44.tgz -> 65-k8s-app-upgrade.sh - stx-ceph-pools-audit | stx-cephfs-provisioner | stx-rbd-provisioner) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release.py $rel - ;; - # NOT SUPPORTED: portieris-1.0-33.tgz - portieris-portieris-psp-rolebinding | portieris-portieris-certs | portieris-portieris) - log "$NAME: migration of helm release $rel is not currently supported." - ;; - # SUPPORTED: ptp-notification-1.0-52.tgz -> 65-k8s-app-upgrade.sh - ptp-ptp-notification-psp-rolebinding | ptp-ptp-notification) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release.py $rel - ;; - # SUPPORTED: snmp-1.0-25.tgz -> 65-k8s-app-upgrade.sh - ns-snmp) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release.py $rel - ;; - # NOT SUPPORTED: vault-1.0-23.tgz - sva-vault-psp-rolebinding | sva-vault) - log "$NAME: migration of helm release $rel is not currently supported." - ;; - # For Openstack's helm releases. - osh-openstack-*) - log "$NAME: migrating helm release $rel." - /usr/bin/migrate_helm_release_openstack.py $rel - ;; - *) - log "$NAME: migration of UNKNOWN helm release $rel is not currently supported." - ;; - esac - done -} - -if [ "$ACTION" == "activate" ]; then - # TODO: double check the inclusive condition. - if [[ "$TO_RELEASE" == "22.12" && "$FROM_RELEASE" == "22.06" ]]; then - log "upgrade to 22.12, skip" - exit 0 - fi - - log "$NAME: Starting Helm release migration from release $FROM_RELEASE to $TO_RELEASE with action $ACTION" - install_helm_2to3 - get_helmv2_config - migrate_apps - helm plugin uninstall 2to3 -fi - -exit 0