Application dirs and overrides updates
This commit includes the following changes to support updating versioned application: - helm application overrides are tied to a specific application - each application files are uploaded to its own versioned directory e.g. stx-openstack-1.0-13 app files will be located at, /opt/platform/armada/19.01/stx-openstack/1.0-13/... /opt/platform/helm/19.01/stx-openstack/1.0-13/... /scratch/apps/stx-openstack/1.0-13/... Story: 2005350 Task: 33439 Change-Id: I75555deda57181d069f24d458dda5bf08e7e17cc Signed-off-by: Angie Wang <angie.wang@windriver.com>
This commit is contained in:
parent
07587a049a
commit
b978111f19
|
@ -1,2 +1,2 @@
|
|||
SRC_DIR="cgts-client"
|
||||
TIS_PATCH_VER=65
|
||||
TIS_PATCH_VER=66
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#
|
||||
|
||||
from cgtsclient.common import base
|
||||
from cgtsclient import exc
|
||||
|
||||
|
||||
class App(base.Resource):
|
||||
|
@ -66,3 +67,12 @@ class AppManager(base.Manager):
|
|||
:param name: app_name
|
||||
"""
|
||||
return self._delete(self._path(app_name))
|
||||
|
||||
|
||||
def _find_app(cc, app_name):
|
||||
try:
|
||||
app = cc.app.get(app_name)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Application not found: %s' % app_name)
|
||||
else:
|
||||
return app
|
||||
|
|
|
@ -21,17 +21,18 @@ class HelmManager(base.Manager):
|
|||
def _path(name=''):
|
||||
return '/v1/helm_charts/%s' % name
|
||||
|
||||
def list_charts(self):
|
||||
def list_charts(self, app):
|
||||
"""Get list of charts
|
||||
|
||||
For each chart it will show any overrides for that chart along
|
||||
with the namespace of the overrides.
|
||||
"""
|
||||
return self._list(self._path(), 'charts')
|
||||
return self._list(self._path() + '?app_name=' + app, 'charts')
|
||||
|
||||
def get_overrides(self, name, namespace):
|
||||
def get_overrides(self, app, name, namespace):
|
||||
"""Get overrides for a given chart.
|
||||
|
||||
:param app_name: name of application
|
||||
:param name: name of the chart
|
||||
:param namespace: namespace for the chart overrides
|
||||
|
||||
|
@ -39,14 +40,17 @@ class HelmManager(base.Manager):
|
|||
specified chart.
|
||||
"""
|
||||
try:
|
||||
return self._list(self._path(name) + '?namespace=' + namespace)[0]
|
||||
return self._list(self._path(app) +
|
||||
'?name=' + name +
|
||||
'&namespace=' + namespace)[0]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def update_overrides(self, name, namespace,
|
||||
def update_overrides(self, app, name, namespace,
|
||||
flag='reset', override_values={}):
|
||||
"""Update overrides for a given chart.
|
||||
|
||||
:param app_name: name of application
|
||||
:param name: name of the chart
|
||||
:param namespace: namespace for the chart overrides
|
||||
:param flag: 'reuse' or 'reset' to indicate how to handle existing
|
||||
|
@ -56,12 +60,17 @@ class HelmManager(base.Manager):
|
|||
This will return the end-user overrides for the specified chart.
|
||||
"""
|
||||
body = {'flag': flag, 'values': override_values}
|
||||
return self._update(self._path(name) + '?namespace=' + namespace, body)
|
||||
return self._update(self._path(app) +
|
||||
'?name=' + name +
|
||||
'&namespace=' + namespace, body)
|
||||
|
||||
def delete_overrides(self, name, namespace):
|
||||
def delete_overrides(self, app, name, namespace):
|
||||
"""Delete overrides for a given chart.
|
||||
|
||||
:param app_name: name of application
|
||||
:param name: name of the chart
|
||||
:param namespace: namespace for the chart overrides
|
||||
"""
|
||||
return self._delete(self._path(name) + '?namespace=' + namespace)
|
||||
return self._delete(self._path(app) +
|
||||
'?name=' + name +
|
||||
'&namespace=' + namespace)
|
||||
|
|
|
@ -11,6 +11,7 @@ import yaml
|
|||
|
||||
from cgtsclient.common import utils
|
||||
from cgtsclient import exc
|
||||
from cgtsclient.v1 import app as app_utils
|
||||
|
||||
|
||||
def _print_helm_chart(chart):
|
||||
|
@ -22,12 +23,32 @@ def _print_helm_chart(chart):
|
|||
utils.print_dict(ordereddata)
|
||||
|
||||
|
||||
def _find_overrides(cc, app, chart, namespace):
|
||||
charts = cc.helm.list_charts(app.name)
|
||||
for c in charts:
|
||||
if chart == c.name and namespace in c.namespaces:
|
||||
break
|
||||
else:
|
||||
raise exc.CommandError('Chart overrides %s:%s for application '
|
||||
'%s not found' %
|
||||
(chart, namespace, app.name))
|
||||
|
||||
return c
|
||||
|
||||
|
||||
@utils.arg('app',
|
||||
metavar='<app name>',
|
||||
help="Name of the application")
|
||||
def do_helm_override_list(cc, args):
|
||||
"""List system helm charts."""
|
||||
charts = cc.helm.list_charts()
|
||||
app = app_utils._find_app(cc, args.app)
|
||||
charts = cc.helm.list_charts(app.name)
|
||||
utils.print_list(charts, ['name', 'namespaces'], ['chart name', 'overrides namespaces'], sortby=0)
|
||||
|
||||
|
||||
@utils.arg('app',
|
||||
metavar='<app name>',
|
||||
help="Name of the application")
|
||||
@utils.arg('chart', metavar='<chart name>',
|
||||
help="Name of chart")
|
||||
@utils.arg('namespace',
|
||||
|
@ -35,14 +56,15 @@ def do_helm_override_list(cc, args):
|
|||
help="namespace of chart overrides")
|
||||
def do_helm_override_show(cc, args):
|
||||
"""Show overrides for chart."""
|
||||
try:
|
||||
chart = cc.helm.get_overrides(args.chart, args.namespace)
|
||||
_print_helm_chart(chart)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('chart overrides not found: %s:%s' % (
|
||||
args.chart, args.namespace))
|
||||
app = app_utils._find_app(cc, args.app)
|
||||
_find_overrides(cc, app, args.chart, args.namespace)
|
||||
chart = cc.helm.get_overrides(args.app, args.chart, args.namespace)
|
||||
_print_helm_chart(chart)
|
||||
|
||||
|
||||
@utils.arg('app',
|
||||
metavar='<app name>',
|
||||
help="Name of the application")
|
||||
@utils.arg('chart',
|
||||
metavar='<chart name>',
|
||||
help="Name of chart")
|
||||
|
@ -51,15 +73,16 @@ def do_helm_override_show(cc, args):
|
|||
help="namespace of chart overrides")
|
||||
def do_helm_override_delete(cc, args):
|
||||
"""Delete overrides for a chart."""
|
||||
try:
|
||||
cc.helm.delete_overrides(args.chart, args.namespace)
|
||||
print('Deleted chart overrides for %s:%s' % (
|
||||
args.chart, args.namespace))
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('chart overrides not found: %s:%s' % (
|
||||
args.chart, args.namespace))
|
||||
app = app_utils._find_app(cc, args.app)
|
||||
_find_overrides(cc, app, args.chart, args.namespace)
|
||||
cc.helm.delete_overrides(args.app, args.chart, args.namespace)
|
||||
print('Deleted chart overrides %s:%s for application %s' %
|
||||
(args.chart, args.namespace, args.app))
|
||||
|
||||
|
||||
@utils.arg('app',
|
||||
metavar='<app name>',
|
||||
help="Name of the application")
|
||||
@utils.arg('chart',
|
||||
metavar='<chart name>',
|
||||
help="Name of chart")
|
||||
|
@ -85,6 +108,9 @@ def do_helm_override_delete(cc, args):
|
|||
def do_helm_override_update(cc, args):
|
||||
"""Update helm chart user overrides."""
|
||||
|
||||
app = app_utils._find_app(cc, args.app)
|
||||
_find_overrides(cc, app, args.chart, args.namespace)
|
||||
|
||||
# This logic results in similar behaviour to "helm upgrade".
|
||||
flag = 'reset'
|
||||
if args.reuse_values and not args.reset_values:
|
||||
|
@ -114,10 +140,6 @@ def do_helm_override_update(cc, args):
|
|||
'set': override_set,
|
||||
}
|
||||
|
||||
try:
|
||||
chart = cc.helm.update_overrides(args.chart, args.namespace,
|
||||
flag, overrides)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('helm chart not found: %s:%s' % (
|
||||
args.chart, args.namespace))
|
||||
chart = cc.helm.update_overrides(args.app, args.chart, args.namespace,
|
||||
flag, overrides)
|
||||
_print_helm_chart(chart)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
SRC_DIR="sysinv"
|
||||
TIS_PATCH_VER=318
|
||||
TIS_PATCH_VER=319
|
||||
|
|
|
@ -23,30 +23,28 @@ LOG = log.getLogger(__name__)
|
|||
|
||||
class HelmChartsController(rest.RestController):
|
||||
|
||||
@wsme_pecan.wsexpose(wtypes.text)
|
||||
def get_all(self):
|
||||
@wsme_pecan.wsexpose(wtypes.text, wtypes.text)
|
||||
def get_all(self, app_name):
|
||||
"""Provides information about the available charts to override."""
|
||||
|
||||
supported_apps = pecan.request.rpcapi.get_helm_applications(
|
||||
pecan.request.context)
|
||||
all_charts = {}
|
||||
for app in supported_apps:
|
||||
namespaces = pecan.request.rpcapi.get_helm_application_namespaces(
|
||||
pecan.request.context, app)
|
||||
for chart in namespaces:
|
||||
if chart not in all_charts:
|
||||
all_charts[chart] = namespaces[chart]
|
||||
else:
|
||||
all_charts[chart] = list(set().union(all_charts[chart],
|
||||
namespaces[chart]))
|
||||
try:
|
||||
objects.kube_app.get_by_name(
|
||||
pecan.request.context, app_name)
|
||||
except exception.KubeAppNotFound:
|
||||
raise wsme.exc.ClientSideError(_("Application %s not found." % app_name))
|
||||
|
||||
namespaces = pecan.request.rpcapi.get_helm_application_namespaces(
|
||||
pecan.request.context, app_name)
|
||||
charts = [{'name': chart, 'namespaces': namespaces[chart]}
|
||||
for chart in namespaces]
|
||||
|
||||
charts = [{'name': c, 'namespaces': ns} for c, ns in all_charts.items()]
|
||||
return {'charts': charts}
|
||||
|
||||
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, wtypes.text)
|
||||
def get_one(self, name, namespace):
|
||||
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, wtypes.text, wtypes.text)
|
||||
def get_one(self, app_name, name, namespace):
|
||||
"""Retrieve information about the given chart.
|
||||
|
||||
:param app_name: name of application
|
||||
:param name: name of helm chart
|
||||
:param namespace: namespace of chart overrides
|
||||
"""
|
||||
|
@ -54,9 +52,13 @@ class HelmChartsController(rest.RestController):
|
|||
|
||||
# Get any user-specified overrides.
|
||||
try:
|
||||
db_chart = objects.helm_overrides.get_by_name(
|
||||
pecan.request.context, name, namespace)
|
||||
app = objects.kube_app.get_by_name(
|
||||
pecan.request.context, app_name)
|
||||
db_chart = objects.helm_overrides.get_by_appid_name(
|
||||
pecan.request.context, app.id, name, namespace)
|
||||
user_overrides = db_chart.user_overrides
|
||||
except exception.KubeAppNotFound:
|
||||
raise wsme.exc.ClientSideError(_("Application %s not found." % app_name))
|
||||
except exception.HelmOverrideNotFound:
|
||||
user_overrides = ''
|
||||
|
||||
|
@ -92,10 +94,12 @@ class HelmChartsController(rest.RestController):
|
|||
if not namespace:
|
||||
raise wsme.exc.ClientSideError(_("Namespace must be specified."))
|
||||
|
||||
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, wtypes.text, wtypes.text, wtypes.text)
|
||||
def patch(self, name, namespace, flag, values):
|
||||
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, wtypes.text,
|
||||
wtypes.text, wtypes.text, wtypes.text)
|
||||
def patch(self, app_name, name, namespace, flag, values):
|
||||
""" Update user overrides.
|
||||
|
||||
:param app_name: name of application
|
||||
:param name: chart name
|
||||
:param namespace: namespace of chart overrides
|
||||
:param flag: one of "reuse" or "reset", describes how to handle
|
||||
|
@ -110,15 +114,20 @@ class HelmChartsController(rest.RestController):
|
|||
# Get any stored user overrides for this chart. We'll need this
|
||||
# object later either way.
|
||||
try:
|
||||
db_chart = objects.helm_overrides.get_by_name(
|
||||
pecan.request.context, name, namespace)
|
||||
app = objects.kube_app.get_by_name(
|
||||
pecan.request.context, app_name)
|
||||
db_chart = objects.helm_overrides.get_by_appid_name(
|
||||
pecan.request.context, app.id, name, namespace)
|
||||
except exception.KubeAppNotFound:
|
||||
raise wsme.exc.ClientSideError(_("Application %s not found." % app_name))
|
||||
except exception.HelmOverrideNotFound:
|
||||
pecan.request.dbapi.helm_override_create({
|
||||
'name': name,
|
||||
'namespace': namespace,
|
||||
'user_overrides': ''})
|
||||
db_chart = objects.helm_overrides.get_by_name(
|
||||
pecan.request.context, name, namespace)
|
||||
'user_overrides': '',
|
||||
'app_id': app.id})
|
||||
db_chart = objects.helm_overrides.get_by_appid_name(
|
||||
pecan.request.context, app.id, name, namespace)
|
||||
|
||||
if flag == 'reuse':
|
||||
if db_chart.user_overrides is not None:
|
||||
|
@ -150,16 +159,21 @@ class HelmChartsController(rest.RestController):
|
|||
|
||||
return chart
|
||||
|
||||
@wsme_pecan.wsexpose(None, wtypes.text, wtypes.text, status_code=204)
|
||||
def delete(self, name, namespace):
|
||||
@wsme_pecan.wsexpose(None, wtypes.text, wtypes.text,
|
||||
wtypes.text, status_code=204)
|
||||
def delete(self, app_name, name, namespace):
|
||||
"""Delete user overrides for a chart
|
||||
|
||||
:param app_name: name of application
|
||||
:param name: chart name.
|
||||
:param namespace: namespace of chart overrides
|
||||
"""
|
||||
self.validate_name_and_namespace(name, namespace)
|
||||
try:
|
||||
pecan.request.dbapi.helm_override_update(name, namespace,
|
||||
app = objects.kube_app.get_by_name(pecan.request.context, app_name)
|
||||
pecan.request.dbapi.helm_override_update(app.id, name, namespace,
|
||||
{'user_overrides': None})
|
||||
except exception.KubeAppNotFound:
|
||||
raise wsme.exc.ClientSideError(_("Application %s not found." % app_name))
|
||||
except exception.HelmOverrideNotFound:
|
||||
pass
|
||||
|
|
|
@ -22,14 +22,16 @@ CONF = cfg.CONF
|
|||
|
||||
def create_app_overrides_action(path, app_name=None, namespace=None):
|
||||
dbapi = api.get_instance()
|
||||
operator = helm.HelmOperator(dbapi=dbapi, path=path)
|
||||
operator.generate_helm_application_overrides(app_name, mode=None, cnamespace=namespace)
|
||||
operator = helm.HelmOperator(dbapi=dbapi)
|
||||
operator.generate_helm_application_overrides(path, app_name, mode=None,
|
||||
cnamespace=namespace)
|
||||
|
||||
|
||||
def create_armada_app_overrides_action(path, app_name=None, namespace=None):
|
||||
dbapi = api.get_instance()
|
||||
operator = helm.HelmOperator(dbapi=dbapi, path=path)
|
||||
operator.generate_helm_application_overrides(app_name, mode=None, cnamespace=namespace,
|
||||
operator = helm.HelmOperator(dbapi=dbapi)
|
||||
operator.generate_helm_application_overrides(path, app_name, mode=None,
|
||||
cnamespace=namespace,
|
||||
armada_format=True,
|
||||
armada_chart_info=None,
|
||||
combined=False)
|
||||
|
@ -37,8 +39,8 @@ def create_armada_app_overrides_action(path, app_name=None, namespace=None):
|
|||
|
||||
def create_chart_override_action(path, chart_name=None, namespace=None):
|
||||
dbapi = api.get_instance()
|
||||
operator = helm.HelmOperator(dbapi=dbapi, path=path)
|
||||
operator.generate_helm_chart_overrides(chart_name, namespace)
|
||||
operator = helm.HelmOperator(dbapi=dbapi)
|
||||
operator.generate_helm_chart_overrides(path, chart_name, namespace)
|
||||
|
||||
|
||||
def add_action_parsers(subparsers):
|
||||
|
|
|
@ -67,23 +67,30 @@ DOCKER_REGISTRY_SECRET = 'default-registry-key'
|
|||
|
||||
|
||||
# Helper functions
|
||||
def generate_armada_manifest_filename(app_name, manifest_filename):
|
||||
return os.path.join('/manifests', app_name + '-' + manifest_filename)
|
||||
|
||||
|
||||
def generate_armada_manifest_filename_abs(app_name, manifest_filename):
|
||||
return os.path.join(constants.APP_SYNCED_DATA_PATH,
|
||||
def generate_armada_manifest_filename(app_name, app_version, manifest_filename):
|
||||
return os.path.join('/manifests', app_name, app_version,
|
||||
app_name + '-' + manifest_filename)
|
||||
|
||||
|
||||
def generate_manifest_filename_abs(app_name, manifest_filename):
|
||||
def generate_armada_manifest_dir(app_name, app_version):
|
||||
return os.path.join(constants.APP_SYNCED_DATA_PATH, app_name, app_version)
|
||||
|
||||
|
||||
def generate_armada_manifest_filename_abs(armada_mfile_dir, app_name, manifest_filename):
|
||||
return os.path.join(armada_mfile_dir, app_name + '-' + manifest_filename)
|
||||
|
||||
|
||||
def generate_manifest_filename_abs(app_name, app_version, manifest_filename):
|
||||
return os.path.join(constants.APP_INSTALL_PATH,
|
||||
app_name, manifest_filename)
|
||||
app_name, app_version, manifest_filename)
|
||||
|
||||
|
||||
def generate_images_filename_abs(app_name):
|
||||
return os.path.join(constants.APP_SYNCED_DATA_PATH,
|
||||
app_name + '-images.yaml')
|
||||
def generate_images_filename_abs(armada_mfile_dir, app_name):
|
||||
return os.path.join(armada_mfile_dir, app_name + '-images.yaml')
|
||||
|
||||
|
||||
def generate_overrides_dir(app_name, app_version):
|
||||
return os.path.join(common.HELM_OVERRIDES_PATH, app_name, app_version)
|
||||
|
||||
|
||||
def create_app_path(path):
|
||||
|
@ -134,18 +141,20 @@ class AppOperator(object):
|
|||
def _cleanup(self, app):
|
||||
"""" Remove application directories and override files """
|
||||
try:
|
||||
if app.system_app and app.status != constants.APP_UPLOAD_FAILURE:
|
||||
self._remove_chart_overrides(app.armada_mfile_abs)
|
||||
if os.path.exists(app.overrides_dir):
|
||||
shutil.rmtree(os.path.dirname(
|
||||
app.overrides_dir))
|
||||
|
||||
if os.path.exists(app.armada_mfile_abs):
|
||||
os.unlink(app.armada_mfile_abs)
|
||||
if os.path.exists(app.imgfile_abs):
|
||||
os.unlink(app.imgfile_abs)
|
||||
if os.path.exists(app.armada_mfile_dir):
|
||||
shutil.rmtree(os.path.dirname(
|
||||
app.armada_mfile_dir))
|
||||
|
||||
if os.path.exists(app.path):
|
||||
shutil.rmtree(app.path)
|
||||
shutil.rmtree(os.path.dirname(
|
||||
app.path))
|
||||
except OSError as e:
|
||||
LOG.error(e)
|
||||
raise
|
||||
|
||||
def _update_app_status(self, app, new_status=None, new_progress=None):
|
||||
""" Persist new app status """
|
||||
|
@ -244,10 +253,13 @@ class AppOperator(object):
|
|||
orig_uid, orig_gid = get_app_install_root_path_ownership()
|
||||
|
||||
try:
|
||||
# One time set up of Armada manifest path for the system
|
||||
# One time set up of base armada manifest path for the system
|
||||
if not os.path.isdir(constants.APP_SYNCED_DATA_PATH):
|
||||
os.makedirs(constants.APP_SYNCED_DATA_PATH)
|
||||
|
||||
if not os.path.isdir(app.armada_mfile_dir):
|
||||
os.makedirs(app.armada_mfile_dir)
|
||||
|
||||
if not os.path.isdir(app.path):
|
||||
create_app_path(app.path)
|
||||
|
||||
|
@ -307,7 +319,7 @@ class AppOperator(object):
|
|||
image_tags.extend(ids)
|
||||
return list(set(image_tags))
|
||||
|
||||
def _get_image_tags_by_charts(self, app_images_file, app_manifest_file):
|
||||
def _get_image_tags_by_charts(self, app_images_file, app_manifest_file, overrides_dir):
|
||||
""" Mine the image tags for charts from the images file. Add the
|
||||
image tags to the manifest file if the image tags from the charts
|
||||
do not exist in both overrides file and manifest file. Convert
|
||||
|
@ -349,7 +361,7 @@ class AppOperator(object):
|
|||
|
||||
# Get the image tags from the overrides file
|
||||
overrides = chart_namespace + '-' + chart_name + '.yaml'
|
||||
app_overrides_file = os.path.join(common.HELM_OVERRIDES_PATH, overrides)
|
||||
app_overrides_file = os.path.join(overrides_dir, overrides)
|
||||
if os.path.exists(app_overrides_file):
|
||||
try:
|
||||
with open(app_overrides_file, 'r') as f:
|
||||
|
@ -443,12 +455,12 @@ class AppOperator(object):
|
|||
LOG.info("Generating application overrides...")
|
||||
app.charts = self._get_list_of_charts(app.armada_mfile_abs)
|
||||
self._helm.generate_helm_application_overrides(
|
||||
app.name, mode=None, cnamespace=None, armada_format=True,
|
||||
armada_chart_info=app.charts, combined=True)
|
||||
app.overrides_dir, app.name, mode=None, cnamespace=None,
|
||||
armada_format=True, armada_chart_info=app.charts, combined=True)
|
||||
self._save_images_list_by_charts(app)
|
||||
# Get the list of images from the updated images overrides
|
||||
images_to_download = self._get_image_tags_by_charts(
|
||||
app.imgfile_abs, app.armada_mfile_abs)
|
||||
app.imgfile_abs, app.armada_mfile_abs, app.overrides_dir)
|
||||
else:
|
||||
# For custom apps, mine image tags from application path
|
||||
images_to_download = self._get_image_tags_by_path(app.path)
|
||||
|
@ -505,7 +517,7 @@ class AppOperator(object):
|
|||
saved_images_list = self._retrieve_images_list(app.imgfile_abs)
|
||||
saved_download_images_list = list(saved_images_list.get("download_images"))
|
||||
images_to_download = self._get_image_tags_by_charts(
|
||||
app.imgfile_abs, app.armada_mfile_abs)
|
||||
app.imgfile_abs, app.armada_mfile_abs, app.overrides_dir)
|
||||
if set(saved_download_images_list) != set(images_to_download):
|
||||
saved_images_list.update({"download_images": images_to_download})
|
||||
with open(app.imgfile_abs, 'wb') as f:
|
||||
|
@ -858,7 +870,7 @@ class AppOperator(object):
|
|||
pass
|
||||
return charts
|
||||
|
||||
def _get_overrides_files(self, charts, app_name, mode):
|
||||
def _get_overrides_files(self, overrides_dir, charts, app_name, mode):
|
||||
"""Returns list of override files or None, used in
|
||||
application-install and application-delete."""
|
||||
|
||||
|
@ -867,8 +879,7 @@ class AppOperator(object):
|
|||
|
||||
for chart in charts:
|
||||
overrides = chart.namespace + '-' + chart.name + '.yaml'
|
||||
overrides_file = os.path.join(common.HELM_OVERRIDES_PATH,
|
||||
overrides)
|
||||
overrides_file = os.path.join(overrides_dir, overrides)
|
||||
if not os.path.exists(overrides_file):
|
||||
missing_overrides.append(overrides_file)
|
||||
else:
|
||||
|
@ -881,8 +892,7 @@ class AppOperator(object):
|
|||
chart.name, chart.namespace, app_name, mode):
|
||||
overrides = chart.namespace + '-' + chart.name + \
|
||||
'-meta' + '.yaml'
|
||||
overrides_file = os.path.join(common.HELM_OVERRIDES_PATH,
|
||||
overrides)
|
||||
overrides_file = os.path.join(overrides_dir, overrides)
|
||||
if not os.path.exists(overrides_file):
|
||||
missing_overrides.append(overrides_file)
|
||||
else:
|
||||
|
@ -893,15 +903,17 @@ class AppOperator(object):
|
|||
return None
|
||||
return available_overrides
|
||||
|
||||
def _generate_armada_overrides_str(self, overrides_files):
|
||||
return " ".join([' --values /overrides/{0}'.format(os.path.basename(i))
|
||||
def _generate_armada_overrides_str(self, app_name, app_version, overrides_files):
|
||||
return " ".join([' --values /overrides/{0}/{1}/{2}'.format(app_name, app_version,
|
||||
os.path.basename(i))
|
||||
for i in overrides_files])
|
||||
|
||||
def _remove_chart_overrides(self, manifest_file):
|
||||
def _remove_chart_overrides(self, overrides_dir, manifest_file):
|
||||
charts = self._get_list_of_charts(manifest_file)
|
||||
for chart in charts:
|
||||
if chart.name in self._helm.chart_operators:
|
||||
self._helm.remove_helm_chart_overrides(chart.name,
|
||||
self._helm.remove_helm_chart_overrides(overrides_dir,
|
||||
chart.name,
|
||||
chart.namespace)
|
||||
|
||||
def _make_armada_request_with_monitor(self, app, request, overrides_str=None):
|
||||
|
@ -1129,10 +1141,10 @@ class AppOperator(object):
|
|||
self._upload_helm_charts(app)
|
||||
|
||||
self._save_images_list(app)
|
||||
self._update_app_status(app, constants.APP_UPLOAD_SUCCESS)
|
||||
if app.patch_dependencies:
|
||||
self._app._patch_report_app_dependencies(
|
||||
app.name, app.patch_dependencies)
|
||||
self._update_app_status(app, constants.APP_UPLOAD_SUCCESS)
|
||||
LOG.info("Application (%s) upload completed." % app.name)
|
||||
except exception.KubeAppUploadFailure as e:
|
||||
LOG.exception(e)
|
||||
|
@ -1182,16 +1194,19 @@ class AppOperator(object):
|
|||
app, new_progress=constants.APP_PROGRESS_GENERATE_OVERRIDES)
|
||||
LOG.info("Generating application overrides...")
|
||||
self._helm.generate_helm_application_overrides(
|
||||
app.name, mode, cnamespace=None, armada_format=True,
|
||||
armada_chart_info=app.charts, combined=True)
|
||||
overrides_files = self._get_overrides_files(app.charts, app.name, mode)
|
||||
app.overrides_dir, app.name, mode, cnamespace=None,
|
||||
armada_format=True, armada_chart_info=app.charts, combined=True)
|
||||
overrides_files = self._get_overrides_files(app.overrides_dir,
|
||||
app.charts,
|
||||
app.name, mode)
|
||||
if overrides_files:
|
||||
LOG.info("Application overrides generated.")
|
||||
# Ensure all chart overrides are readable by Armada
|
||||
for file in overrides_files:
|
||||
os.chmod(file, 0o644)
|
||||
overrides_str =\
|
||||
self._generate_armada_overrides_str(overrides_files)
|
||||
self._generate_armada_overrides_str(app.name, app.version,
|
||||
overrides_files)
|
||||
self._update_app_status(
|
||||
app, new_progress=constants.APP_PROGRESS_DOWNLOAD_IMAGES)
|
||||
self._download_images(app)
|
||||
|
@ -1321,22 +1336,33 @@ class AppOperator(object):
|
|||
def __init__(self, rpc_app, is_system_app):
|
||||
self._kube_app = rpc_app
|
||||
self.path = os.path.join(constants.APP_INSTALL_PATH,
|
||||
self._kube_app.get('name'))
|
||||
self._kube_app.get('name'),
|
||||
self._kube_app.get('app_version'))
|
||||
self.charts_dir = os.path.join(self.path, 'charts')
|
||||
self.images_dir = os.path.join(self.path, 'images')
|
||||
self.tarfile = None
|
||||
self.downloaded_tarfile = False
|
||||
self.system_app = is_system_app
|
||||
self.overrides_dir = generate_overrides_dir(
|
||||
self._kube_app.get('name'),
|
||||
self._kube_app.get('app_version'))
|
||||
self.armada_mfile_dir = generate_armada_manifest_dir(
|
||||
self._kube_app.get('name'),
|
||||
self._kube_app.get('app_version'))
|
||||
self.armada_mfile = generate_armada_manifest_filename(
|
||||
self._kube_app.get('name'),
|
||||
self._kube_app.get('app_version'),
|
||||
self._kube_app.get('manifest_file'))
|
||||
self.armada_mfile_abs = generate_armada_manifest_filename_abs(
|
||||
self.armada_mfile_dir,
|
||||
self._kube_app.get('name'),
|
||||
self._kube_app.get('manifest_file'))
|
||||
self.mfile_abs = generate_manifest_filename_abs(
|
||||
self._kube_app.get('name'),
|
||||
self._kube_app.get('app_version'),
|
||||
self._kube_app.get('manifest_file'))
|
||||
self.imgfile_abs = generate_images_filename_abs(
|
||||
self.armada_mfile_dir,
|
||||
self._kube_app.get('name'))
|
||||
|
||||
self.patch_dependencies = []
|
||||
|
@ -1379,25 +1405,35 @@ class AppOperator(object):
|
|||
self._kube_app.manifest_name = new_mname
|
||||
self._kube_app.manifest_file = new_mfile
|
||||
self.armada_mfile = generate_armada_manifest_filename(
|
||||
self.name, new_mfile)
|
||||
self.name, self.version, new_mfile)
|
||||
self.armada_mfile_abs = generate_armada_manifest_filename_abs(
|
||||
self.name, new_mfile)
|
||||
self.armada_mfile_dir, self.name, new_mfile)
|
||||
self.mfile_abs = generate_manifest_filename_abs(
|
||||
self.name, new_mfile)
|
||||
self.name, self.version, new_mfile)
|
||||
|
||||
def regenerate_application_info(self, new_name, new_version, new_patch_dependencies):
|
||||
self._kube_app.name = new_name
|
||||
self._kube_app.app_version = new_version
|
||||
self.system_app = \
|
||||
(self.name == constants.HELM_APP_OPENSTACK)
|
||||
self.imgfile_abs = \
|
||||
generate_images_filename_abs(self.name)
|
||||
|
||||
new_armada_dir = generate_armada_manifest_dir(
|
||||
self.name, self.version)
|
||||
shutil.move(self.armada_mfile_dir, new_armada_dir)
|
||||
shutil.rmtree(os.path.dirname(self.armada_mfile_dir))
|
||||
self.armada_mfile_dir = new_armada_dir
|
||||
|
||||
new_path = os.path.join(
|
||||
constants.APP_INSTALL_PATH, self.name)
|
||||
os.rename(self.path, new_path)
|
||||
constants.APP_INSTALL_PATH, self.name, self.version)
|
||||
shutil.move(self.path, new_path)
|
||||
shutil.rmtree(os.path.dirname(self.path))
|
||||
self.path = new_path
|
||||
|
||||
self.charts_dir = os.path.join(self.path, 'charts')
|
||||
self.images_dir = os.path.join(self.path, 'images')
|
||||
self.imgfile_abs = \
|
||||
generate_images_filename_abs(self.armada_mfile_dir, self.name)
|
||||
self.overrides_dir = generate_overrides_dir(self.name, self.version)
|
||||
self.patch_dependencies = new_patch_dependencies
|
||||
|
||||
|
||||
|
|
|
@ -7358,9 +7358,10 @@ class Connection(api.Connection):
|
|||
raise exception.CertificateNotFound(uuid)
|
||||
query.delete()
|
||||
|
||||
def _helm_override_get(self, name, namespace):
|
||||
def _helm_override_get(self, app_id, name, namespace):
|
||||
query = model_query(models.HelmOverrides)
|
||||
query = query.filter_by(name=name, namespace=namespace)
|
||||
query = query.filter_by(
|
||||
app_id=app_id, name=name, namespace=namespace)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
|
@ -7382,12 +7383,13 @@ class Connection(api.Connection):
|
|||
(values['name']))
|
||||
raise exception.HelmOverrideAlreadyExists(
|
||||
name=values['name'], namespace=values['namespace'])
|
||||
return self._helm_override_get(values['name'],
|
||||
return self._helm_override_get(values['app_id'],
|
||||
values['name'],
|
||||
values['namespace'])
|
||||
|
||||
@objects.objectify(objects.helm_overrides)
|
||||
def helm_override_get(self, name, namespace):
|
||||
return self._helm_override_get(name, namespace)
|
||||
def helm_override_get(self, app_id, name, namespace):
|
||||
return self._helm_override_get(app_id, name, namespace)
|
||||
|
||||
@objects.objectify(objects.helm_overrides)
|
||||
def helm_override_get_all(self):
|
||||
|
@ -7395,10 +7397,11 @@ class Connection(api.Connection):
|
|||
return query.all()
|
||||
|
||||
@objects.objectify(objects.helm_overrides)
|
||||
def helm_override_update(self, name, namespace, values):
|
||||
def helm_override_update(self, app_id, name, namespace, values):
|
||||
with _session_for_write() as session:
|
||||
query = model_query(models.HelmOverrides, session=session)
|
||||
query = query.filter_by(name=name, namespace=namespace)
|
||||
query = query.filter_by(
|
||||
app_id=app_id, name=name, namespace=namespace)
|
||||
|
||||
count = query.update(values, synchronize_session='fetch')
|
||||
if count == 0:
|
||||
|
@ -7406,10 +7409,11 @@ class Connection(api.Connection):
|
|||
namespace=namespace)
|
||||
return query.one()
|
||||
|
||||
def helm_override_destroy(self, name, namespace):
|
||||
def helm_override_destroy(self, app_id, name, namespace):
|
||||
with _session_for_write() as session:
|
||||
query = model_query(models.HelmOverrides, session=session)
|
||||
query = query.filter_by(name=name, namespace=namespace)
|
||||
query = query.filter_by(
|
||||
app_id=app_id, name=name, namespace=namespace)
|
||||
|
||||
try:
|
||||
query.one()
|
||||
|
@ -7573,6 +7577,7 @@ class Connection(api.Connection):
|
|||
"operation is not allowed while status is " + app.status
|
||||
raise exception.KubeAppDeleteFailure(
|
||||
name=name,
|
||||
version=app.app_version,
|
||||
reason=failure_reason)
|
||||
except NoResultFound:
|
||||
raise exception.KubeAppNotFound(name)
|
||||
|
|
|
@ -25,7 +25,7 @@ def upgrade(migrate_engine):
|
|||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
# Define and create the helm_overrides table.
|
||||
# Define and create the kube_app table.
|
||||
kube_app = Table(
|
||||
'kube_app',
|
||||
meta,
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
|
||||
from sqlalchemy import DateTime, String, Text, Integer
|
||||
from sqlalchemy import Column, MetaData, Table, UniqueConstraint
|
||||
from sqlalchemy import Column, MetaData, Table, UniqueConstraint, ForeignKey
|
||||
|
||||
from sysinv.openstack.common import log
|
||||
|
||||
|
@ -25,6 +25,8 @@ def upgrade(migrate_engine):
|
|||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
Table('kube_app', meta, autoload=True)
|
||||
|
||||
# Define and create the helm_overrides table.
|
||||
helm_overrides = Table(
|
||||
'helm_overrides',
|
||||
|
@ -36,7 +38,9 @@ def upgrade(migrate_engine):
|
|||
Column('name', String(255), nullable=False),
|
||||
Column('namespace', String(255), nullable=False),
|
||||
Column('user_overrides', Text, nullable=True),
|
||||
UniqueConstraint('name', 'namespace', name='u_name_namespace'),
|
||||
Column('app_id', Integer,
|
||||
ForeignKey('kube_app.id', ondelete='CASCADE')),
|
||||
UniqueConstraint('name', 'namespace', 'app_id', name='u_app_name_namespace'),
|
||||
|
||||
mysql_engine=ENGINE,
|
||||
mysql_charset=CHARSET,
|
|
@ -1677,7 +1677,9 @@ class HelmOverrides(Base):
|
|||
namespace = Column(String(255), nullable=False)
|
||||
user_overrides = Column(Text, nullable=True)
|
||||
system_overrides = Column(JSONEncodedDict, nullable=True)
|
||||
UniqueConstraint('name', 'namespace', name='u_name_namespace')
|
||||
app_id = Column(Integer, ForeignKey('kube_app.id', ondelete='CASCADE'))
|
||||
kube_app = relationship("KubeApp", lazy="joined", join_depth=1)
|
||||
UniqueConstraint('name', 'namespace', 'app_id', name='u_app_name_namespace')
|
||||
|
||||
|
||||
class Label(Base):
|
||||
|
|
|
@ -45,12 +45,8 @@ def helm_context(func):
|
|||
class HelmOperator(object):
|
||||
"""Class to encapsulate helm override operations for System Inventory"""
|
||||
|
||||
def __init__(self, dbapi=None, path=None):
|
||||
if path is None:
|
||||
path = common.HELM_OVERRIDES_PATH
|
||||
|
||||
def __init__(self, dbapi=None):
|
||||
self.dbapi = dbapi
|
||||
self.path = path
|
||||
|
||||
# register chart operators for lookup
|
||||
self.chart_operators = {}
|
||||
|
@ -377,7 +373,7 @@ class HelmOperator(object):
|
|||
return values
|
||||
|
||||
@helm_context
|
||||
def generate_helm_chart_overrides(self, chart_name, cnamespace=None):
|
||||
def generate_helm_chart_overrides(self, path, chart_name, cnamespace=None):
|
||||
"""Generate system helm chart overrides
|
||||
|
||||
This method will generate system helm chart override an write them to a
|
||||
|
@ -399,7 +395,8 @@ class HelmOperator(object):
|
|||
overrides = self._get_helm_chart_overrides(
|
||||
chart_name,
|
||||
cnamespace)
|
||||
self._write_chart_overrides(chart_name,
|
||||
self._write_chart_overrides(path,
|
||||
chart_name,
|
||||
cnamespace,
|
||||
overrides)
|
||||
except Exception as e:
|
||||
|
@ -424,7 +421,8 @@ class HelmOperator(object):
|
|||
return overrides
|
||||
|
||||
@helm_context
|
||||
def generate_helm_application_overrides(self, app_name, mode=None,
|
||||
def generate_helm_application_overrides(self, path, app_name,
|
||||
mode=None,
|
||||
cnamespace=None,
|
||||
armada_format=False,
|
||||
armada_chart_info=None,
|
||||
|
@ -450,6 +448,11 @@ class HelmOperator(object):
|
|||
"""
|
||||
|
||||
if app_name in self.helm_applications:
|
||||
try:
|
||||
app = self.dbapi.kube_app_get(app_name)
|
||||
except exception.KubeAppNotFound:
|
||||
LOG.exception("Application %s not found." % app_name)
|
||||
|
||||
app_overrides = self._get_helm_application_overrides(app_name,
|
||||
cnamespace)
|
||||
for (chart_name, overrides) in iteritems(app_overrides):
|
||||
|
@ -468,7 +471,7 @@ class HelmOperator(object):
|
|||
for chart_namespace in overrides.keys():
|
||||
try:
|
||||
db_chart = self.dbapi.helm_override_get(
|
||||
chart_name, chart_namespace)
|
||||
app.id, chart_name, chart_namespace)
|
||||
db_user_overrides = db_chart.user_overrides
|
||||
if db_user_overrides:
|
||||
file_overrides.append(yaml.dump(
|
||||
|
@ -495,7 +498,7 @@ class HelmOperator(object):
|
|||
chart_name, armada_chart_repo_name,
|
||||
key, overrides[key])
|
||||
overrides[key] = new_overrides
|
||||
self._write_chart_overrides(chart_name, cnamespace, overrides)
|
||||
self._write_chart_overrides(path, chart_name, cnamespace, overrides)
|
||||
|
||||
# Write any meta-overrides for this chart. These will be in
|
||||
# armada format already.
|
||||
|
@ -507,14 +510,14 @@ class HelmOperator(object):
|
|||
if overrides:
|
||||
chart_meta_name = chart_name + '-meta'
|
||||
self._write_chart_overrides(
|
||||
chart_meta_name, cnamespace, overrides)
|
||||
path, chart_meta_name, cnamespace, overrides)
|
||||
|
||||
elif app_name:
|
||||
LOG.exception("%s application is not supported" % app_name)
|
||||
else:
|
||||
LOG.exception("application name is required")
|
||||
|
||||
def remove_helm_chart_overrides(self, chart_name, cnamespace=None):
|
||||
def remove_helm_chart_overrides(self, path, chart_name, cnamespace=None):
|
||||
"""Remove the overrides files for a chart"""
|
||||
|
||||
if chart_name in self.chart_operators:
|
||||
|
@ -529,7 +532,7 @@ class HelmOperator(object):
|
|||
|
||||
for f in filenames:
|
||||
try:
|
||||
self._remove_overrides(f)
|
||||
self._remove_overrides(path, f)
|
||||
except Exception as e:
|
||||
LOG.exception("failed to remove %s overrides: %s: %s" % (
|
||||
chart_name, f, e))
|
||||
|
@ -537,12 +540,12 @@ class HelmOperator(object):
|
|||
LOG.exception("chart %s not supported for system overrides" %
|
||||
chart_name)
|
||||
|
||||
def _write_chart_overrides(self, chart_name, cnamespace, overrides):
|
||||
def _write_chart_overrides(self, path, chart_name, cnamespace, overrides):
|
||||
"""Write a one or more overrides files for a chart. """
|
||||
|
||||
def _write_file(filename, values):
|
||||
try:
|
||||
self._write_overrides(filename, values)
|
||||
self._write_overrides(path, filename, values)
|
||||
except Exception as e:
|
||||
LOG.exception("failed to write %s overrides: %s: %s" % (
|
||||
chart_name, filename, e))
|
||||
|
@ -553,12 +556,15 @@ class HelmOperator(object):
|
|||
for ns in overrides.keys():
|
||||
_write_file("%s-%s.yaml" % (ns, chart_name), overrides[ns])
|
||||
|
||||
def _write_overrides(self, filename, overrides):
|
||||
def _write_overrides(self, path, filename, overrides):
|
||||
"""Write a single overrides file. """
|
||||
|
||||
filepath = os.path.join(self.path, filename)
|
||||
if not os.path.isdir(path):
|
||||
os.makedirs(path)
|
||||
|
||||
filepath = os.path.join(path, filename)
|
||||
try:
|
||||
fd, tmppath = tempfile.mkstemp(dir=self.path, prefix=filename,
|
||||
fd, tmppath = tempfile.mkstemp(dir=path, prefix=filename,
|
||||
text=True)
|
||||
|
||||
with open(tmppath, 'w') as f:
|
||||
|
@ -569,10 +575,10 @@ class HelmOperator(object):
|
|||
LOG.exception("failed to write overrides file: %s" % filepath)
|
||||
raise
|
||||
|
||||
def _remove_overrides(self, filename):
|
||||
def _remove_overrides(self, path, filename):
|
||||
"""Remove a single overrides file. """
|
||||
|
||||
filepath = os.path.join(self.path, filename)
|
||||
filepath = os.path.join(path, filename)
|
||||
try:
|
||||
if os.path.exists(filepath):
|
||||
os.unlink(filepath)
|
||||
|
|
|
@ -149,7 +149,9 @@ class OpenstackBaseHelm(base.BaseHelm):
|
|||
return None
|
||||
|
||||
try:
|
||||
override = self.dbapi.helm_override_get(name=chart,
|
||||
app = self.dbapi.kube_app_get(constants.HELM_APP_OPENSTACK)
|
||||
override = self.dbapi.helm_override_get(app_id=app.id,
|
||||
name=chart,
|
||||
namespace=namespace)
|
||||
except exception.HelmOverrideNotFound:
|
||||
# Override for this chart not found, so create one
|
||||
|
@ -157,6 +159,7 @@ class OpenstackBaseHelm(base.BaseHelm):
|
|||
values = {
|
||||
'name': chart,
|
||||
'namespace': namespace,
|
||||
'app_id': app.id,
|
||||
}
|
||||
override = self.dbapi.helm_override_create(values=values)
|
||||
except Exception as e:
|
||||
|
@ -176,7 +179,7 @@ class OpenstackBaseHelm(base.BaseHelm):
|
|||
})
|
||||
try:
|
||||
self.dbapi.helm_override_update(
|
||||
name=chart, namespace=namespace, values=values)
|
||||
app_id=app.id, name=chart, namespace=namespace, values=values)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
|
||||
|
@ -337,13 +340,16 @@ class OpenstackBaseHelm(base.BaseHelm):
|
|||
|
||||
def _get_or_generate_ssh_keys(self, chart, namespace):
|
||||
try:
|
||||
override = self.dbapi.helm_override_get(name=chart,
|
||||
app = self.dbapi.kube_app_get(constants.HELM_APP_OPENSTACK)
|
||||
override = self.dbapi.helm_override_get(app_id=app.id,
|
||||
name=chart,
|
||||
namespace=namespace)
|
||||
except exception.HelmOverrideNotFound:
|
||||
# Override for this chart not found, so create one
|
||||
values = {
|
||||
'name': chart,
|
||||
'namespace': namespace,
|
||||
'app_id': app.id
|
||||
}
|
||||
override = self.dbapi.helm_override_create(values=values)
|
||||
|
||||
|
@ -362,7 +368,7 @@ class OpenstackBaseHelm(base.BaseHelm):
|
|||
values['system_overrides'].update({'privatekey': newprivatekey,
|
||||
'publickey': newpublickey})
|
||||
self.dbapi.helm_override_update(
|
||||
name=chart, namespace=namespace, values=values)
|
||||
app_id=app.id, name=chart, namespace=namespace, values=values)
|
||||
|
||||
return newprivatekey, newpublickey
|
||||
|
||||
|
|
|
@ -21,11 +21,13 @@ class HelmOverrides(base.SysinvObject):
|
|||
'namespace': utils.str_or_none,
|
||||
'user_overrides': utils.str_or_none,
|
||||
'system_overrides': utils.dict_or_none,
|
||||
'app_id': int
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_name(cls, context, name, namespace):
|
||||
return cls.dbapi.helm_override_get(name, namespace)
|
||||
def get_by_appid_name(cls, context, app_id, name, namespace):
|
||||
return cls.dbapi.helm_override_get(app_id, name, namespace)
|
||||
|
||||
def save_changes(self, context, updates):
|
||||
self.dbapi.helm_override_update(self.name, self.namespace, updates)
|
||||
self.dbapi.helm_override_update(self.app_id, self.name,
|
||||
self.namespace, updates)
|
||||
|
|
Loading…
Reference in New Issue