114 lines
4.3 KiB
Python
114 lines
4.3 KiB
Python
# Copyright 2017 The Armada Authors.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from shutil import rmtree
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
from armada import const
|
|
from armada.exceptions import chartbuilder_exceptions
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
class ChartBuilder(object):
|
|
'''
|
|
This class handles taking chart intentions as a parameter and turning those
|
|
into proper Helm chart metadata.
|
|
'''
|
|
|
|
@classmethod
|
|
def from_chart_doc(cls, chart, helm):
|
|
'''
|
|
Returns a ChartBuilder defined by an Armada Chart doc.
|
|
|
|
:param chart: Armada Chart doc for which to build the Helm chart.
|
|
'''
|
|
|
|
name = chart['metadata']['name']
|
|
chart_data = chart[const.KEYWORD_DATA]
|
|
source_dir = chart_data['source_dir']
|
|
source_directory = os.path.join(*source_dir)
|
|
dependencies = chart_data.get('dependencies')
|
|
|
|
if dependencies is not None:
|
|
# Ensure `charts` dir exists and is empty.
|
|
charts_dir = os.path.join(source_directory, 'charts')
|
|
charts_path = Path(charts_dir)
|
|
if charts_path.is_dir():
|
|
# NOTE: Ideally we would only delete the subcharts being
|
|
# overridden, and leave the others in place, but we delete all
|
|
# for backward compatibility with the Helm 2 based Armada.
|
|
(rmtree(d) for d in charts_path.iterdir() if d.is_dir())
|
|
else:
|
|
if charts_path.exists():
|
|
# NOTE: Ideally we would throw an error if `charts` is a
|
|
# non-directory, but we don't for backward compatibility
|
|
# with the Helm 2 based Armada.
|
|
charts_path.unlink()
|
|
|
|
charts_path.mkdir()
|
|
|
|
# Add symlinks to dependencies into `charts` dir.
|
|
for chart_dep in dependencies:
|
|
# Handle any recursive dependencies.
|
|
ChartBuilder.from_chart_doc(chart_dep, helm)
|
|
|
|
dep_data = chart_dep[const.KEYWORD_DATA]
|
|
dep_source_dir = dep_data['source_dir']
|
|
dep_source_directory = os.path.join(*dep_source_dir)
|
|
dep_charts_yaml = helm.show_chart(dep_source_directory)
|
|
dep_name = dep_charts_yaml['name']
|
|
dep_target_directory = os.path.join(charts_dir, dep_name)
|
|
Path(dep_target_directory).symlink_to(dep_source_directory)
|
|
|
|
return cls(name, source_directory, helm)
|
|
|
|
def __init__(self, name, source_directory, helm):
|
|
'''
|
|
:param name: A name to use for the chart.
|
|
:param source_directory: The source directory of the Helm chart.
|
|
:param helm: Helm client to calculate the helm chart object.
|
|
'''
|
|
self.name = name
|
|
self.source_directory = source_directory
|
|
self.helm = helm
|
|
|
|
# cache for generated chart object
|
|
self._helm_chart = None
|
|
|
|
# We do a dry-run upgrade here to get the helm chart metadata.
|
|
# Ideally helm would support an explicit machine readable way to
|
|
# get that data so we don't need the dry run upgrade which could
|
|
# fail for other reasons than not being able to get the chart
|
|
# metadata, see:
|
|
# https://github.com/helm/helm/issues/9968
|
|
def get_helm_chart(self, release_id, values):
|
|
'''Return a Helm chart object.
|
|
'''
|
|
LOG.debug(
|
|
"Building chart %s from path %s", self.name, self.source_directory)
|
|
try:
|
|
result = self.helm.upgrade_release(
|
|
self.source_directory, release_id, values=values, dry_run=True)
|
|
return result['chart']
|
|
except Exception as e:
|
|
raise chartbuilder_exceptions.HelmChartBuildException(
|
|
self.name, details=e)
|