OIDC upgrade script
Cherry-picks commit 8293b0af2c
To simplify code review: changes necessary for upgrade from 21.12 to
22.12 are submitted in a subsequent commit.
Additional testing will be addressed under change:
I53ae6fbf1669cd8fbfca6082716333433d32ab80
Original commit log:
These scripts perform helm override check, backup of helm overrides,
conversion of helm overrides and upgrade of the oidc-auth-apps
application.
The backup helm overrides and conversion files will be in named
sub-directories within /opt/oidc-auth-apps. The sub-directory names
reflect the procedure that creates them, but are otherwise arbitrary.
The configuration check ensures the end-user's helm-overrides can be
converted from old Dex to new Dex. The conversion rearranges the helm
overrides to fit into the new Dex values.yaml.
The 50-validate-oidc-auth-apps.py contains the backup, check and
conversion code and will be run on both on the 'from' release as a
pre-upgrade check, and on the 'to' release for backup, and conversion.
The 70-upgrade-oidc-auth-apps.sh script is run at upgrade activate to
remove the old app and apply the new app with converted user overrides.
This invokes 50-validate-oidc-auth-apps.py on the active controller
during upgrade-activate as well.
Depends-On:
https://review.opendev.org/c/starlingx/oidc-auth-armada-app/+/845380
Test plan:
PASS: tox (python2, python36)
PASS: run upgrade script as postgres user
PASS: sequenced commands: check, backup and convert
PASS: conversion of sample configurations with app verification after
PASS: conversion without user overrides
PASS: backup helm-overrides to /opt/oidc-auth-apps as postgres user
PASS: check and conversion of helm override for documentation examples
PASS: push helm overrides back to database
TODO: upgrade-activate
TODO: end-to-end upgrade SX
In-progress: end-to-end upgrade DX
TODO: python3 Debian
Story: 2009838
Task: 45641
Change-Id: I43e528aa6143b0888cbfb7dfb4ad0c7bf1ef94a6
Signed-off-by: Michel Thebeau <Michel.Thebeau@windriver.com>
This commit is contained in:
parent
b42950fd87
commit
2fecb99ae4
496
controllerconfig/controllerconfig/upgrade-scripts/50-validate-oidc-auth-apps.py
Executable file
496
controllerconfig/controllerconfig/upgrade-scripts/50-validate-oidc-auth-apps.py
Executable file
@ -0,0 +1,496 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Conversion of oidc-auth-apps configuration
|
||||
#
|
||||
# Verify the supported configuration during health-query-upgrade.
|
||||
# Backup overrides at upgrade start.
|
||||
# Convert the configuration during upgrade activate.
|
||||
|
||||
from controllerconfig.common import log
|
||||
import copy
|
||||
import os
|
||||
import psycopg2
|
||||
from psycopg2.extras import RealDictCursor
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
log.configure()
|
||||
|
||||
# This script is only valid for to/from releases:
|
||||
ACCEPTED_FROM = ['21.12']
|
||||
ACCEPTED_TO = ['22.06']
|
||||
ACCEPTED_ACTIONS = ['health-check', 'start', 'migrate']
|
||||
|
||||
# this path should have been created by stx-oidc-auth-helm package
|
||||
# with ownership assigned to postgres:postgres
|
||||
BACKUP_PATH = '/opt/oidc-auth-apps'
|
||||
|
||||
# list of charts in oidc-auth-apps; for sanity check only
|
||||
oidc_charts = ['dex', 'oidc-client', 'secret-observer']
|
||||
|
||||
# Hard-coded chart values; matching the fluxcd manifest defaults
|
||||
DEFAULT_HTTPSTLS_MOUNT = '/etc/dex/tls'
|
||||
DEFAULT_HTTPSTLS_MODE = 420
|
||||
DEFAULT_HTTPSTLS_SECRET = 'local-dex.tls'
|
||||
|
||||
# A dictionary of values selected from the overrides yaml during
|
||||
# validate_overrides(). The selected values are used to convert
|
||||
# the yaml from old dex to new dex
|
||||
DEFINES = {}
|
||||
|
||||
# validate yaml, instructions for what configurations accepted
|
||||
validation_yaml = """
|
||||
name: "supported"
|
||||
validation: "children"
|
||||
optional: False
|
||||
accepted: ["extraVolumeMounts", "extraVolumes", "config", "certs"]
|
||||
children:
|
||||
- name: "extraVolumeMounts"
|
||||
validation: "any"
|
||||
optional: True
|
||||
define: "volumeMounts"
|
||||
- name: "extraVolumes"
|
||||
validation: "any"
|
||||
optional: True
|
||||
define: "volumes"
|
||||
- name: "config"
|
||||
validation: "children"
|
||||
optional: False
|
||||
define: "dex_config"
|
||||
children:
|
||||
- name: "web"
|
||||
validation: "children"
|
||||
optional: True
|
||||
children:
|
||||
- name: "tlsCert"
|
||||
validation: "exact"
|
||||
optional: True
|
||||
define: "dex_https_tlsCert"
|
||||
- name: "tlsKey"
|
||||
validation: "exact"
|
||||
optional: True
|
||||
define: "dex_https_tlsKey"
|
||||
- name: "certs"
|
||||
validation: "children"
|
||||
optional: True
|
||||
accepted: ["grpc", "web"]
|
||||
children:
|
||||
- name: "grpc"
|
||||
validation: "children"
|
||||
optional: True
|
||||
accepted: ["secret"]
|
||||
children:
|
||||
- name: "secret"
|
||||
validation: "children"
|
||||
optional: False
|
||||
accepted: ["caName", "clientTlsName", "serverTlsName"]
|
||||
children:
|
||||
- name: "caName"
|
||||
validation: "exact"
|
||||
optional: False
|
||||
define: "tls_secret"
|
||||
- name: "clientTlsName"
|
||||
validation: "exact"
|
||||
optional: False
|
||||
define: "tls_secret"
|
||||
- name: "serverTlsName"
|
||||
validation: "exact"
|
||||
optional: False
|
||||
define: "tls_secret"
|
||||
- name: "web"
|
||||
validation: "children"
|
||||
optional: False
|
||||
accepted: ["secret"]
|
||||
children:
|
||||
- name: "secret"
|
||||
validation: "children"
|
||||
optional: False
|
||||
accepted: ["caName", "tlsName"]
|
||||
children:
|
||||
- name: "caName"
|
||||
validation: "exact"
|
||||
optional: False
|
||||
define: "tls_secret"
|
||||
- name: "tlsName"
|
||||
validation: "exact"
|
||||
optional: False
|
||||
define: "tls_secret"
|
||||
|
||||
"""
|
||||
|
||||
# sql to fetch the user_overrides from DB for oidc-auth-apps
|
||||
sql_overrides = ("SELECT helm_overrides.name, user_overrides"
|
||||
" FROM helm_overrides"
|
||||
" LEFT OUTER JOIN kube_app"
|
||||
" ON helm_overrides.app_id = kube_app.id"
|
||||
" WHERE kube_app.name = 'oidc-auth-apps'")
|
||||
|
||||
sql_update = ("UPDATE helm_overrides"
|
||||
" SET user_overrides = '%s'"
|
||||
" FROM kube_app"
|
||||
" WHERE helm_overrides.app_id = kube_app.id"
|
||||
" AND kube_app.name = 'oidc-auth-apps'"
|
||||
" AND helm_overrides.name = 'dex'")
|
||||
|
||||
|
||||
def get_overrides(conn):
|
||||
"""Fetch helm overrides from DB"""
|
||||
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||
cur.execute(sql_overrides)
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
def backup_overrides(overrides, action='debug'):
|
||||
"""Dump helm overrides from DB to files in BACKUP_PATH"""
|
||||
backup_path = os.path.join(BACKUP_PATH, action)
|
||||
if not os.path.exists(backup_path):
|
||||
os.makedirs(backup_path)
|
||||
field = 'user_overrides'
|
||||
for chart in overrides:
|
||||
name = chart['name']
|
||||
if name not in oidc_charts:
|
||||
LOG.warning("oidc-auth-apps: mismatch chart name '%s'", name)
|
||||
if chart[field]:
|
||||
document = yaml.load(chart[field])
|
||||
if not document:
|
||||
LOG.debug("oidc-auth-apps: %s empty document", name)
|
||||
continue
|
||||
backup_f = '_'.join([name, field])
|
||||
backup_f = '.'.join([backup_f, 'yaml'])
|
||||
backup_f = os.path.join(backup_path, backup_f)
|
||||
try:
|
||||
with open(backup_f, 'w') as file:
|
||||
yaml.dump(document, file, default_flow_style=False)
|
||||
except IOError as e:
|
||||
LOG.error("oidc-auth-apps: IOError: %s; file: %s", e, backup_f)
|
||||
return 1
|
||||
LOG.info("oidc-auth-apps: user_overrides backed up to %s", backup_path)
|
||||
return 0
|
||||
|
||||
|
||||
def validate_value(instruction, value):
|
||||
"""Verify a value"""
|
||||
if instruction['validation'] == 'exact':
|
||||
if type(value) not in [str, bool, int, float]:
|
||||
LOG.error("oidc-auth-apps: value type %s not supported",
|
||||
type(value))
|
||||
return False
|
||||
if 'define' in instruction:
|
||||
if instruction['define'] in DEFINES:
|
||||
if DEFINES[instruction['define']] != value:
|
||||
LOG.error("oidc-auth-apps: defined value is"
|
||||
" mismatched '%s': '%s' != '%s'",
|
||||
instruction['define'],
|
||||
DEFINES[instruction['define']],
|
||||
value)
|
||||
LOG.error("oidc-auth-apps: instruction: %s", instruction)
|
||||
return False
|
||||
else:
|
||||
DEFINES[instruction['define']] = value
|
||||
LOG.debug("oidc-auth-apps: define: '%s' == '%s'",
|
||||
instruction['define'], value)
|
||||
if 'values' in instruction:
|
||||
LOG.error("oidc-auth-apps: validation exact values"
|
||||
" not implemented")
|
||||
return False
|
||||
else:
|
||||
LOG.error("oidc-auth-apps: validation %s not supported",
|
||||
instruction['validation'])
|
||||
return False
|
||||
LOG.debug("oidc-auth-apps: accept %s: %s: %s",
|
||||
instruction['validation'], instruction, value)
|
||||
return True
|
||||
|
||||
|
||||
def printable_item(item):
|
||||
"""remove children from item to make it printable"""
|
||||
printable = {}
|
||||
printable['validation'] = item['validation']
|
||||
printable['name'] = item['name']
|
||||
printable['optional'] = item['optional']
|
||||
if 'define' in item:
|
||||
printable['define'] = item['define']
|
||||
return printable
|
||||
|
||||
|
||||
def define_complex_value(item, yaml_doc):
|
||||
"""Subroutine to fill DEFINES for complex values"""
|
||||
if 'define' in item and item['validation'] != 'exact':
|
||||
# Handle saving of complex values
|
||||
if item['define'] in DEFINES:
|
||||
LOG.error("oidc-auth-apps: complex values comparison"
|
||||
" is not supported: %s", printable_item(item))
|
||||
return False
|
||||
else:
|
||||
DEFINES[item['define']] = copy.deepcopy(yaml_doc[item['name']])
|
||||
LOG.debug("oidc-auth-apps: define: '%s'",
|
||||
item['define'])
|
||||
return True
|
||||
|
||||
|
||||
def validate_item(item, yaml_doc):
|
||||
"""Handle one list item from instruction"""
|
||||
print_item = printable_item(item)
|
||||
# If neither present nor optional: fail
|
||||
# If not present, but optional: pass
|
||||
optional = True
|
||||
if 'optional' in item:
|
||||
optional = item['optional']
|
||||
present = item['name'] in yaml_doc
|
||||
if not (present or optional):
|
||||
LOG.error("oidc-auth-apps: overrides omit required value:"
|
||||
" %s", print_item)
|
||||
return False
|
||||
elif not present:
|
||||
# pass
|
||||
return True
|
||||
if not define_complex_value(item, yaml_doc):
|
||||
return False
|
||||
|
||||
if item['validation'] == 'any':
|
||||
# pass
|
||||
LOG.debug("oidc-auth-apps: accept instruction: %s", print_item)
|
||||
elif item['validation'] == 'exact':
|
||||
if not validate_value(item, yaml_doc[item['name']]):
|
||||
return False
|
||||
elif item['validation'] == 'children':
|
||||
accepted_keys = ['*']
|
||||
if 'accepted' in item:
|
||||
if not validate_accepted(item['accepted'], yaml_doc[item['name']]):
|
||||
return False
|
||||
else:
|
||||
accepted_keys = [x for x in yaml_doc[item['name']]]
|
||||
if not recurse_validate_document(item['children'],
|
||||
yaml_doc[item['name']]):
|
||||
LOG.error("oidc-auth-apps: instruction: %s", print_item)
|
||||
return False
|
||||
else:
|
||||
LOG.debug("oidc-auth-apps: accept instruction: %s: %s",
|
||||
print_item, accepted_keys)
|
||||
else:
|
||||
LOG.error("oidc-auth-apps: instruction %s not implemented",
|
||||
item['validation'])
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def validate_accepted(accepted, yaml_doc):
|
||||
"""Check that each item in yaml is expected"""
|
||||
if type(yaml_doc) is not dict:
|
||||
LOG.error("oidc-auth-apps: accepting from list not implemented")
|
||||
return False
|
||||
error = False
|
||||
for key in yaml_doc:
|
||||
if key not in accepted:
|
||||
error = True
|
||||
LOG.error("oidc-auth-apps: key is not accepted: %s", key)
|
||||
return not error
|
||||
|
||||
|
||||
def recurse_validate_document(instruction, yaml_doc):
|
||||
"""Recursively verify the document against validation yaml"""
|
||||
if type(instruction) is not list:
|
||||
LOG.error("oidc-auth-apps: non-list instruction not implemented")
|
||||
return False
|
||||
for item in instruction:
|
||||
if type(item) is not dict:
|
||||
LOG.error("oidc-auth-apps: non-dict instruction item"
|
||||
" not implemented")
|
||||
return False
|
||||
elif 'validation' not in item:
|
||||
LOG.error("oidc-auth-apps: instruction missing validation")
|
||||
return False
|
||||
elif 'name' not in item:
|
||||
LOG.error("oidc-auth-apps: instruction missing name")
|
||||
return False
|
||||
elif not validate_item(item, yaml_doc):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def validate_document(validation, document):
|
||||
"""Top level, verify the document against validation yaml"""
|
||||
LOG.info("oidc-auth-apps: validating %s", validation['name'])
|
||||
if validation['validation'] != 'children':
|
||||
LOG.warning("oidc-auth-apps: root validation should be"
|
||||
" children not %s", validation['validation'])
|
||||
result = recurse_validate_document(validation['children'], document)
|
||||
if 'accepted' in validation:
|
||||
if not validate_accepted(validation['accepted'], document):
|
||||
return False
|
||||
if validation['optional']:
|
||||
LOG.warning("oidc-auth-apps: root validation is optional")
|
||||
return True
|
||||
return result
|
||||
|
||||
|
||||
def get_chart_override(overrides, chart):
|
||||
"""Get a specific set of overrides from the db value"""
|
||||
chart_ov = None
|
||||
for chart_ov in overrides:
|
||||
if 'name' in chart_ov and chart_ov['name'] == chart:
|
||||
break
|
||||
else:
|
||||
chart_ov = None
|
||||
if not (chart_ov and 'user_overrides' in chart_ov):
|
||||
return None
|
||||
if not chart_ov['user_overrides']:
|
||||
# A sanity check. Really shouldn't see this if oidc-auth-apps
|
||||
# does not have dex overrides - either because the app is not
|
||||
# applied, or because it failed to apply without overrides
|
||||
return None
|
||||
# convert the string to python structures
|
||||
return yaml.load(chart_ov['user_overrides'])
|
||||
|
||||
|
||||
def validate_overrides(overrides):
|
||||
"""Check if the user_overrides are supported"""
|
||||
DEFINES.clear()
|
||||
if not overrides:
|
||||
# dex without overrides isn't configured correctly
|
||||
LOG.error("oidc-auth-apps: no overrides to validate")
|
||||
return False
|
||||
elif type(overrides) is not list:
|
||||
# this shouldn't happen
|
||||
LOG.error("oidc-auth-apps: overrides not list type")
|
||||
return False
|
||||
# Find dex; only dex helm needs conversion
|
||||
document = get_chart_override(overrides, 'dex')
|
||||
if not document:
|
||||
LOG.error("oidc-auth-apps: no dex user_overrides to validate")
|
||||
return False
|
||||
validate = yaml.load(validation_yaml)
|
||||
return validate_document(validate, document)
|
||||
|
||||
|
||||
def get_httpstls_mount():
|
||||
"""Use the default unless the end-user had overridden it"""
|
||||
if 'dex_https_tlsCert' in DEFINES:
|
||||
return os.path.dirname(DEFINES['dex_https_tlsCert'])
|
||||
# The default matches oic-auth-apps flucd manifest defaults
|
||||
return DEFAULT_HTTPSTLS_MOUNT
|
||||
|
||||
|
||||
def get_httpstls_secret():
|
||||
"""Use the default unless the end-user had overridden it"""
|
||||
if 'tls_secret' in DEFINES:
|
||||
return DEFINES['tls_secret']
|
||||
# The default matches oic-auth-apps flucd manifest defaults
|
||||
return DEFAULT_HTTPSTLS_SECRET
|
||||
|
||||
|
||||
def merge_new_overrides():
|
||||
"""Read DEFINES and prepare new overrides yaml"""
|
||||
# Take the dex config as is:
|
||||
new_doc = {'config': copy.deepcopy(DEFINES['dex_config'])}
|
||||
# Convert old dex certs.web.secret to https-tls volume/volumeMounts
|
||||
mount = {'mountPath': get_httpstls_mount(), 'name': 'https-tls'}
|
||||
vol = {'secret': {'secretName': get_httpstls_secret(),
|
||||
'defaultMode': DEFAULT_HTTPSTLS_MODE},
|
||||
'name': 'https-tls'}
|
||||
# Take 'extra' volumes and mounts that may exist in old dex
|
||||
# This is expected to be the WAD certificate
|
||||
volumes = []
|
||||
volumeMounts = []
|
||||
if 'volumes' in DEFINES:
|
||||
volumes = copy.deepcopy(DEFINES['volumes'])
|
||||
if 'volumeMounts' in DEFINES:
|
||||
volumeMounts = copy.deepcopy(DEFINES['volumeMounts'])
|
||||
|
||||
# only add volumes/mounts if 'extra' was specified, or
|
||||
# if there was non-default mount
|
||||
if volumes or 'tls_secret' in DEFINES:
|
||||
volumes.append(vol)
|
||||
if volumeMounts or 'dex_https_tlsCert' in DEFINES:
|
||||
volumeMounts.append(mount)
|
||||
if volumes:
|
||||
new_doc['volumes'] = volumes
|
||||
if volumeMounts:
|
||||
new_doc['volumeMounts'] = volumeMounts
|
||||
return new_doc
|
||||
|
||||
|
||||
def convert_overrides(overrides, conn):
|
||||
"""Convert the user_overrides from old dex to new"""
|
||||
LOG.info("oidc-auth-apps: converting dex overrides")
|
||||
if not validate_overrides(overrides):
|
||||
return 1
|
||||
new_doc = merge_new_overrides()
|
||||
res = backup_overrides(overrides, action='migrate')
|
||||
if res != 0:
|
||||
return res
|
||||
# replace the dex user overrides
|
||||
new_str = yaml.dump(new_doc, default_flow_style=False)
|
||||
for override in overrides:
|
||||
if override['name'] == 'dex':
|
||||
override['user_overrides'] = new_str
|
||||
res = backup_overrides(overrides, action='converted')
|
||||
return res
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
if action not in ACCEPTED_ACTIONS:
|
||||
LOG.debug("oidc-auth-apps: omit %s, %s, %s",
|
||||
from_release, to_release, action)
|
||||
return 0
|
||||
elif from_release not in ACCEPTED_FROM:
|
||||
LOG.error("oidc-auth-apps: upgrade script not valid from release %s",
|
||||
from_release)
|
||||
return 1
|
||||
elif to_release not in ACCEPTED_TO:
|
||||
LOG.error("oidc-auth-apps: upgrade script not valid to release %s",
|
||||
to_release)
|
||||
return 1
|
||||
|
||||
try:
|
||||
conn = psycopg2.connect("dbname=sysinv user=postgres")
|
||||
overrides = get_overrides(conn)
|
||||
except Exception as ex:
|
||||
LOG.exception("oidc-auth-apps: %s", ex)
|
||||
return 1
|
||||
if not overrides:
|
||||
LOG.error("oidc-auth-apps: failed to fetch overrides")
|
||||
return 1
|
||||
elif not get_chart_override(overrides, 'dex'):
|
||||
LOG.info("oidc-auth-apps: no dex overrides to convert")
|
||||
return 0
|
||||
|
||||
if action == 'health-check':
|
||||
if validate_overrides(overrides):
|
||||
LOG.info("oidc-auth-apps: upgrade script health-check: success")
|
||||
return 0
|
||||
return 1
|
||||
elif action == 'start':
|
||||
return backup_overrides(overrides, action='start')
|
||||
elif action == 'migrate':
|
||||
convert_overrides(overrides, conn)
|
||||
# A failure of oidc-auth-apps overrides conversion is unhandled.
|
||||
# A patch for 21.12 release is needed to pre-test the
|
||||
# compatibility of user overrides with expected configurations.
|
||||
# 22.06 version of oidc-auth-apps will fail to apply if overrides
|
||||
# are not converted.
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
228
controllerconfig/controllerconfig/upgrade-scripts/70-upgrade-oidc-auth-apps.sh
Executable file
228
controllerconfig/controllerconfig/upgrade-scripts/70-upgrade-oidc-auth-apps.sh
Executable file
@ -0,0 +1,228 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This migration script is used for replacing an app during the
|
||||
# activate stage of a platform upgrade. The app is not otherwise
|
||||
# handled by 65-k8s-app-upgrade.sh. The code will:
|
||||
# - remove the old app version
|
||||
# - run app specific code with is inserted into the script
|
||||
# - apply the new app version
|
||||
#
|
||||
# The script is based on 64-upgrade-cert-manager.sh. Logic for
|
||||
# determining application versions is copied from 65-k8s-app-upgrade.sh
|
||||
# application upgrade script in order to keep things consistent.
|
||||
#
|
||||
# This script is intended initially as a generic template.
|
||||
#
|
||||
# The current copy is writen for oidc-auth-apps
|
||||
|
||||
# The migration scripts are passed these parameters:
|
||||
NAME=$(basename $0)
|
||||
FROM_RELEASE=$1
|
||||
TO_RELEASE=$2
|
||||
ACTION=$3
|
||||
|
||||
# only run this script during upgrade-activate
|
||||
if [ "$ACTION" != "activate" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# only run if from 21.12 release
|
||||
if [ "$FROM_RELEASE" != "21.12" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PLATFORM_APPLICATION_PATH='/usr/local/share/applications/helm'
|
||||
PATH=$PATH:/usr/local/sbin
|
||||
|
||||
# conversion script; this script will convert the helm overrides
|
||||
# reading from postgres and putting overrides into /opt/oidc-auth-apps
|
||||
CONV_SCRIPT='/etc/upgrade.d/50-validate-oidc-auth-apps.py'
|
||||
CONV_PARAMS="$FROM_RELEASE $TO_RELEASE migrate"
|
||||
|
||||
DELETE_RESULT_SLEEP=10
|
||||
DELETE_RESULT_ATTEMPTS=6 # ~1 min to delete app
|
||||
UPLOAD_RESULT_SLEEP=10
|
||||
UPLOAD_RESULT_ATTEMPTS=24 # ~4 min to upload app
|
||||
APPLY_RESULT_SLEEP=30
|
||||
APPLY_RESULT_ATTEMPTS=30 # ~15 min to update app
|
||||
REMOVE_RESULT_SLEEP=10
|
||||
REMOVE_RESULT_ATTEMPTS=48 # ~8 min to remove app
|
||||
|
||||
source /etc/platform/openrc
|
||||
source /etc/platform/platform.conf
|
||||
|
||||
# This will log to /var/log/platform.log
|
||||
function log {
|
||||
logger -p local1.info $1
|
||||
}
|
||||
|
||||
EXISTING_APP_NAME='oidc-auth-apps'
|
||||
EXISTING_APP_INFO=$(system application-show $EXISTING_APP_NAME --column app_version --column status --format yaml)
|
||||
EXISTING_APP_VERSION=$(echo ${EXISTING_APP_INFO} | sed 's/.*app_version:[[:space:]]\(\S*\).*/\1/')
|
||||
EXISTING_APP_STATUS=$(echo ${EXISTING_APP_INFO} | sed 's/.*status:[[:space:]]\(\S*\).*/\1/')
|
||||
ORIGINAL_APP_STATUS=$EXISTING_APP_STATUS
|
||||
|
||||
# oidc-auth-apps has user overrides converted and saved for
|
||||
# re-apply at this time
|
||||
OIDC_OVERRIDES="/opt/oidc-auth-apps/converted"
|
||||
OIDC_CHARTS="dex oidc-client secret-observer"
|
||||
function oidc_specific_handling {
|
||||
for chart in $OIDC_CHARTS; do
|
||||
chart_f="${OIDC_OVERRIDES}/${chart}_user_overrides.yaml"
|
||||
if [ ! -f "$chart_f" ]; then
|
||||
continue
|
||||
fi
|
||||
system helm-override-update oidc-auth-apps "${chart}" kube-system \
|
||||
--values="${chart_f}" \
|
||||
|| return 1
|
||||
done
|
||||
}
|
||||
|
||||
# Extract the app name and version from the tarball name: app_name-version.tgz
|
||||
UPGRADE_TARBALL="$(find $PLATFORM_APPLICATION_PATH -name "${EXISTING_APP_NAME}*.tgz")"
|
||||
filecount="$( echo "$UPGRADE_TARBALL" | wc -w )"
|
||||
if [ -z "$UPGRADE_TARBALL" -o "$filecount" -ne 1 ]; then
|
||||
log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, upgrade tarball not found (${filecount}). Exiting for manual intervention..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
re='^('${EXISTING_APP_NAME}')-([0-9]+\.[0-9]+-[0-9]+).tgz'
|
||||
[[ "$(basename $UPGRADE_TARBALL)" =~ $re ]]
|
||||
UPGRADE_APP_NAME=${BASH_REMATCH[1]}
|
||||
UPGRADE_APP_VERSION=${BASH_REMATCH[2]}
|
||||
|
||||
# Accept the application in the following states
|
||||
ACCEPTED_STATES="applied uploaded"
|
||||
if [[ " $ACCEPTED_STATES " != *" $EXISTING_APP_STATUS "* ]]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${EXISTING_APP_VERSION}, in bad state ${EXISTING_APP_STATUS}. Exiting for manual intervention..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# assuming application is in applied state, but log it anyways
|
||||
log "$NAME: $EXISTING_APP_NAME, version $EXISTING_APP_VERSION, is currently in the state: $EXISTING_APP_STATUS"
|
||||
|
||||
# only upgrade the application if the versions dont match
|
||||
# in case the upgrade activate failed due to other reasons, and this
|
||||
# is not the first time this script is run
|
||||
if [ "x${UPGRADE_APP_VERSION}" == "x${EXISTING_APP_VERSION}" ]; then
|
||||
log "$NAME: $UPGRADE_APP_NAME, version $UPGRADE_APP_VERSION, is the same."
|
||||
exit 0
|
||||
else
|
||||
# The 50-validate-oidc-auth-apps.py is used to convert helm
|
||||
# overrides. Run it here on the active controller during
|
||||
# uprade-activate
|
||||
su postgres -c "$CONV_SCRIPT $CONV_PARAMS"
|
||||
|
||||
if [ "$ORIGINAL_APP_STATUS" != "uploaded" ]; then
|
||||
# remove old app version
|
||||
log "$NAME: Removing ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}"
|
||||
system application-remove -f ${EXISTING_APP_NAME}
|
||||
|
||||
# Wait on the remove, should be somewhat quick
|
||||
for tries in $(seq 1 $REMOVE_RESULT_ATTEMPTS); do
|
||||
EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value)
|
||||
if [ "${EXISTING_APP_STATUS}" == 'uploaded' ]; then
|
||||
log "$NAME: ${EXISTING_APP_NAME} has been removed."
|
||||
break
|
||||
fi
|
||||
sleep $REMOVE_RESULT_SLEEP
|
||||
done
|
||||
|
||||
if [ $tries == $REMOVE_RESULT_ATTEMPTS ]; then
|
||||
log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not removed in the allocated time. Exiting for manual intervention..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# delete old app
|
||||
log "$NAME: Deleting ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}"
|
||||
system application-delete -f ${EXISTING_APP_NAME}
|
||||
|
||||
# Wait on the delete, should be quick
|
||||
for tries in $(seq 1 $DELETE_RESULT_ATTEMPTS); do
|
||||
EXISTING_APP_STATUS=$(system application-show $EXISTING_APP_NAME --column status --format value)
|
||||
if [ -z "${EXISTING_APP_STATUS}" ]; then
|
||||
log "$NAME: ${EXISTING_APP_NAME} has been deleted."
|
||||
break
|
||||
fi
|
||||
sleep $DELETE_RESULT_SLEEP
|
||||
done
|
||||
|
||||
if [ $tries == $DELETE_RESULT_ATTEMPTS ]; then
|
||||
log "$NAME: ${EXISTING_APP_NAME}, version ${EXISTING_APP_VERSION}, was not deleted in the allocated time. Exiting for manual intervention..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# upload new app version
|
||||
log "$NAME: Uploading ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION} from $UPGRADE_TARBALL"
|
||||
system application-upload $UPGRADE_TARBALL
|
||||
# Wait on the upload, should be quick
|
||||
for tries in $(seq 1 $UPLOAD_RESULT_ATTEMPTS); do
|
||||
UPGRADE_APP_STATUS=$(system application-show $UPGRADE_APP_NAME --column status --format value)
|
||||
if [ "${UPGRADE_APP_STATUS}" == 'uploaded' ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME} has been uploaded."
|
||||
break
|
||||
fi
|
||||
sleep $UPLOAD_RESULT_SLEEP
|
||||
done
|
||||
|
||||
if [ $tries == $UPLOAD_RESULT_ATTEMPTS ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, was not uploaded in the allocated time. Exiting for manual intervention..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$OIDC_OVERRIDES" ]; then
|
||||
# this is a soft error, the upgrades procedure should not
|
||||
# be affected by the absence of helm-overrides. Either the
|
||||
# application is not configured, or the conversion of overrides
|
||||
# was not possible
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, no helm overrides to set. Upgrade of ${UPGRADE_APP_NAME} complete."
|
||||
exit 0
|
||||
fi
|
||||
oidc_specific_handling
|
||||
if [ $? -ne 0 ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, Helm overrides not set. Exiting for manual intervention..."
|
||||
if [ "$ORIGINAL_APP_STATUS" == "uploaded" ]; then
|
||||
# the application that is not applied does not interfere
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$ORIGINAL_APP_STATUS" == "uploaded" ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}: upload complete"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# dex won't apply without overrides, do not try
|
||||
if [ ! -f "${OIDC_OVERRIDES}/dex_user_overrides.yaml" ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}: dex does not have overrides"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# apply new app version
|
||||
log "$NAME: Applying ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}"
|
||||
system application-apply ${UPGRADE_APP_NAME}
|
||||
|
||||
# Wait on the apply
|
||||
for tries in $(seq 1 $APPLY_RESULT_ATTEMPTS); do
|
||||
UPGRADE_APP_STATUS=$(system application-show $UPGRADE_APP_NAME --column status --format value)
|
||||
if [ "${UPGRADE_APP_STATUS}" == 'applied' ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME} has been applied."
|
||||
break
|
||||
fi
|
||||
sleep $APPLY_RESULT_SLEEP
|
||||
done
|
||||
|
||||
if [ $tries == $APPLY_RESULT_ATTEMPTS ]; then
|
||||
log "$NAME: ${UPGRADE_APP_NAME}, version ${UPGRADE_APP_VERSION}, was not applied in the allocated time. Exiting for manual intervention..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
Loading…
Reference in New Issue
Block a user