Introduce v2 docs
This introduces v2 docs in order to allow users to opt in to breaking changes, while still supporting v1 docs for a time so folks can migrate. At some point v1 doc support will be removed. This initial version of v2 docs is experimental. Further breaking changes will be made before v2 docs are finalized. A v1-v2 migration guide is included in the documentation. This also refactors the internal data model to include the full document structure, such as `metadata` and `schema`, so that different behavior can be acheived for v1, v2, etc. Change-Id: Ia0d44ff4276ef4c27f78706ab02c88aa421a307f
This commit is contained in:
parent
9a43213198
commit
8a50591dbf
|
@ -133,12 +133,12 @@ class TestReleasesManifestController(api.BaseResource):
|
||||||
armada_obj = Manifest(
|
armada_obj = Manifest(
|
||||||
documents, target_manifest=target_manifest).get_manifest()
|
documents, target_manifest=target_manifest).get_manifest()
|
||||||
|
|
||||||
prefix = armada_obj.get(const.KEYWORD_ARMADA).get(const.KEYWORD_PREFIX)
|
prefix = armada_obj[const.KEYWORD_DATA][const.KEYWORD_PREFIX]
|
||||||
known_releases = [release[0] for release in tiller.list_charts()]
|
known_releases = [release[0] for release in tiller.list_charts()]
|
||||||
|
|
||||||
message = {'tests': {'passed': [], 'skipped': [], 'failed': []}}
|
message = {'tests': {'passed': [], 'skipped': [], 'failed': []}}
|
||||||
|
|
||||||
for group in armada_obj.get(const.KEYWORD_ARMADA).get(
|
for group in armada_obj.get(const.KEYWORD_DATA).get(
|
||||||
const.KEYWORD_GROUPS):
|
const.KEYWORD_GROUPS):
|
||||||
for ch in group.get(const.KEYWORD_CHARTS):
|
for ch in group.get(const.KEYWORD_CHARTS):
|
||||||
chart = ch['chart']
|
chart = ch['chart']
|
||||||
|
|
|
@ -126,13 +126,14 @@ class DeleteChartManifest(CliAction):
|
||||||
documents = list(yaml.safe_load_all(f.read()))
|
documents = list(yaml.safe_load_all(f.read()))
|
||||||
try:
|
try:
|
||||||
armada_obj = Manifest(documents).get_manifest()
|
armada_obj = Manifest(documents).get_manifest()
|
||||||
prefix = armada_obj.get(const.KEYWORD_ARMADA).get(
|
prefix = armada_obj.get(const.KEYWORD_DATA).get(
|
||||||
const.KEYWORD_PREFIX)
|
const.KEYWORD_PREFIX)
|
||||||
|
|
||||||
for group in armada_obj.get(const.KEYWORD_ARMADA).get(
|
for group in armada_obj.get(const.KEYWORD_DATA).get(
|
||||||
const.KEYWORD_GROUPS):
|
const.KEYWORD_GROUPS):
|
||||||
for ch in group.get(const.KEYWORD_CHARTS):
|
for ch in group.get(const.KEYWORD_DATA).get(
|
||||||
chart = ch.get('chart')
|
const.KEYWORD_CHARTS):
|
||||||
|
chart = ch.get(const.KEYWORD_DATA)
|
||||||
release_name = release_prefixer(
|
release_name = release_prefixer(
|
||||||
prefix, chart.get('release'))
|
prefix, chart.get('release'))
|
||||||
if release_name in known_release_names:
|
if release_name in known_release_names:
|
||||||
|
|
|
@ -147,10 +147,10 @@ class TestChartManifest(CliAction):
|
||||||
armada_obj = Manifest(
|
armada_obj = Manifest(
|
||||||
documents,
|
documents,
|
||||||
target_manifest=self.target_manifest).get_manifest()
|
target_manifest=self.target_manifest).get_manifest()
|
||||||
prefix = armada_obj.get(const.KEYWORD_ARMADA).get(
|
prefix = armada_obj.get(const.KEYWORD_DATA).get(
|
||||||
const.KEYWORD_PREFIX)
|
const.KEYWORD_PREFIX)
|
||||||
|
|
||||||
for group in armada_obj.get(const.KEYWORD_ARMADA).get(
|
for group in armada_obj.get(const.KEYWORD_DATA).get(
|
||||||
const.KEYWORD_GROUPS):
|
const.KEYWORD_GROUPS):
|
||||||
for ch in group.get(const.KEYWORD_CHARTS):
|
for ch in group.get(const.KEYWORD_CHARTS):
|
||||||
chart = ch['chart']
|
chart = ch['chart']
|
||||||
|
|
|
@ -88,7 +88,7 @@ class ChartDeployAwareLogger(logging.Logger):
|
||||||
def _log(self, level, msg, *args, **kwargs):
|
def _log(self, level, msg, *args, **kwargs):
|
||||||
chart = get_current_chart()
|
chart = get_current_chart()
|
||||||
if chart:
|
if chart:
|
||||||
name = chart['chart_name']
|
name = chart['metadata']['name']
|
||||||
prefix = '[chart={}]: '.format(name)
|
prefix = '[chart={}]: '.format(name)
|
||||||
else:
|
else:
|
||||||
prefix = ''
|
prefix = ''
|
||||||
|
|
|
@ -12,11 +12,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Documents
|
# Keywords
|
||||||
DOCUMENT_CHART = 'armada/Chart/v1'
|
KEYWORD_DATA = 'data'
|
||||||
DOCUMENT_GROUP = 'armada/ChartGroup/v1'
|
|
||||||
DOCUMENT_MANIFEST = 'armada/Manifest/v1'
|
|
||||||
KEYWORD_ARMADA = 'armada'
|
|
||||||
KEYWORD_PREFIX = 'release_prefix'
|
KEYWORD_PREFIX = 'release_prefix'
|
||||||
KEYWORD_GROUPS = 'chart_groups'
|
KEYWORD_GROUPS = 'chart_groups'
|
||||||
KEYWORD_CHARTS = 'chart_group'
|
KEYWORD_CHARTS = 'chart_group'
|
||||||
|
|
|
@ -104,13 +104,14 @@ class Armada(object):
|
||||||
raise tiller_exceptions.TillerServicesUnavailableException()
|
raise tiller_exceptions.TillerServicesUnavailableException()
|
||||||
|
|
||||||
# Clone the chart sources
|
# Clone the chart sources
|
||||||
manifest_data = self.manifest.get(const.KEYWORD_ARMADA, {})
|
manifest_data = self.manifest.get(const.KEYWORD_DATA, {})
|
||||||
for group in manifest_data.get(const.KEYWORD_GROUPS, []):
|
for group in manifest_data.get(const.KEYWORD_GROUPS, []):
|
||||||
for ch in group.get(const.KEYWORD_CHARTS, []):
|
for ch in group.get(const.KEYWORD_DATA).get(
|
||||||
|
const.KEYWORD_CHARTS, []):
|
||||||
self.get_chart(ch)
|
self.get_chart(ch)
|
||||||
|
|
||||||
def get_chart(self, ch):
|
def get_chart(self, ch):
|
||||||
chart = ch.get('chart', {})
|
chart = ch.get(const.KEYWORD_DATA)
|
||||||
chart_source = chart.get('source', {})
|
chart_source = chart.get('source', {})
|
||||||
location = chart_source.get('location')
|
location = chart_source.get('location')
|
||||||
ct_type = chart_source.get('type')
|
ct_type = chart_source.get('type')
|
||||||
|
@ -158,10 +159,10 @@ class Armada(object):
|
||||||
self.chart_cache[source_key] = repo_dir
|
self.chart_cache[source_key] = repo_dir
|
||||||
chart['source_dir'] = (self.chart_cache.get(source_key), subpath)
|
chart['source_dir'] = (self.chart_cache.get(source_key), subpath)
|
||||||
else:
|
else:
|
||||||
chart_name = chart.get('chart_name')
|
name = chart['metadata']['name']
|
||||||
raise source_exceptions.ChartSourceException(ct_type, chart_name)
|
raise source_exceptions.ChartSourceException(ct_type, name)
|
||||||
|
|
||||||
for dep in ch.get('chart', {}).get('dependencies', []):
|
for dep in ch.get(const.KEYWORD_DATA, {}).get('dependencies', []):
|
||||||
self.get_chart(dep)
|
self.get_chart(dep)
|
||||||
|
|
||||||
def sync(self):
|
def sync(self):
|
||||||
|
@ -185,11 +186,12 @@ class Armada(object):
|
||||||
|
|
||||||
known_releases = self.tiller.list_releases()
|
known_releases = self.tiller.list_releases()
|
||||||
|
|
||||||
manifest_data = self.manifest.get(const.KEYWORD_ARMADA, {})
|
manifest_data = self.manifest.get(const.KEYWORD_DATA, {})
|
||||||
prefix = manifest_data.get(const.KEYWORD_PREFIX)
|
prefix = manifest_data.get(const.KEYWORD_PREFIX)
|
||||||
|
|
||||||
for chartgroup in manifest_data.get(const.KEYWORD_GROUPS, []):
|
for cg in manifest_data.get(const.KEYWORD_GROUPS, []):
|
||||||
cg_name = chartgroup.get('name', '<missing name>')
|
chartgroup = cg.get(const.KEYWORD_DATA)
|
||||||
|
cg_name = cg.get('metadata').get('name')
|
||||||
cg_desc = chartgroup.get('description', '<missing description>')
|
cg_desc = chartgroup.get('description', '<missing description>')
|
||||||
cg_sequenced = chartgroup.get('sequenced',
|
cg_sequenced = chartgroup.get('sequenced',
|
||||||
False) or self.force_wait
|
False) or self.force_wait
|
||||||
|
@ -198,11 +200,10 @@ class Armada(object):
|
||||||
cg_desc, cg_sequenced,
|
cg_desc, cg_sequenced,
|
||||||
' (forced)' if self.force_wait else '')
|
' (forced)' if self.force_wait else '')
|
||||||
|
|
||||||
# TODO(MarshM): Deprecate the `test_charts` key
|
# TODO: Remove when v1 doc support is removed.
|
||||||
cg_test_all_charts = chartgroup.get('test_charts')
|
cg_test_all_charts = chartgroup.get('test_charts')
|
||||||
|
|
||||||
cg_charts = chartgroup.get(const.KEYWORD_CHARTS, [])
|
cg_charts = chartgroup.get(const.KEYWORD_CHARTS, [])
|
||||||
charts = map(lambda x: x.get('chart', {}), cg_charts)
|
|
||||||
|
|
||||||
def deploy_chart(chart):
|
def deploy_chart(chart):
|
||||||
set_current_chart(chart)
|
set_current_chart(chart)
|
||||||
|
@ -217,7 +218,7 @@ class Armada(object):
|
||||||
|
|
||||||
# Returns whether or not there was a failure
|
# Returns whether or not there was a failure
|
||||||
def handle_result(chart, get_result):
|
def handle_result(chart, get_result):
|
||||||
name = chart['chart_name']
|
name = chart['metadata']['name']
|
||||||
try:
|
try:
|
||||||
result = get_result()
|
result = get_result()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -229,7 +230,7 @@ class Armada(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if cg_sequenced:
|
if cg_sequenced:
|
||||||
for chart in charts:
|
for chart in cg_charts:
|
||||||
if (handle_result(chart, lambda: deploy_chart(chart))):
|
if (handle_result(chart, lambda: deploy_chart(chart))):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
@ -237,7 +238,7 @@ class Armada(object):
|
||||||
max_workers=len(cg_charts)) as executor:
|
max_workers=len(cg_charts)) as executor:
|
||||||
future_to_chart = {
|
future_to_chart = {
|
||||||
executor.submit(deploy_chart, chart): chart
|
executor.submit(deploy_chart, chart): chart
|
||||||
for chart in charts
|
for chart in cg_charts
|
||||||
}
|
}
|
||||||
|
|
||||||
for future in as_completed(future_to_chart):
|
for future in as_completed(future_to_chart):
|
||||||
|
@ -260,7 +261,7 @@ class Armada(object):
|
||||||
if self.enable_chart_cleanup:
|
if self.enable_chart_cleanup:
|
||||||
self._chart_cleanup(
|
self._chart_cleanup(
|
||||||
prefix,
|
prefix,
|
||||||
self.manifest[const.KEYWORD_ARMADA][const.KEYWORD_GROUPS], msg)
|
self.manifest[const.KEYWORD_DATA][const.KEYWORD_GROUPS], msg)
|
||||||
|
|
||||||
LOG.info('Done applying manifest.')
|
LOG.info('Done applying manifest.')
|
||||||
return msg
|
return msg
|
||||||
|
|
|
@ -41,7 +41,8 @@ class ChartDeploy(object):
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.tiller = tiller
|
self.tiller = tiller
|
||||||
|
|
||||||
def execute(self, chart, cg_test_all_charts, prefix, known_releases):
|
def execute(self, ch, cg_test_all_charts, prefix, known_releases):
|
||||||
|
chart = ch[const.KEYWORD_DATA]
|
||||||
namespace = chart.get('namespace')
|
namespace = chart.get('namespace')
|
||||||
release = chart.get('release')
|
release = chart.get('release')
|
||||||
release_name = r.release_prefixer(prefix, release)
|
release_name = r.release_prefixer(prefix, release)
|
||||||
|
@ -73,7 +74,7 @@ class ChartDeploy(object):
|
||||||
# Begin Chart timeout deadline
|
# Begin Chart timeout deadline
|
||||||
deadline = time.time() + chart_wait.get_timeout()
|
deadline = time.time() + chart_wait.get_timeout()
|
||||||
|
|
||||||
chartbuilder = ChartBuilder(chart)
|
chartbuilder = ChartBuilder(ch)
|
||||||
new_chart = chartbuilder.get_helm_chart()
|
new_chart = chartbuilder.get_helm_chart()
|
||||||
|
|
||||||
# TODO(mark-burnett): It may be more robust to directly call
|
# TODO(mark-burnett): It may be more robust to directly call
|
||||||
|
|
|
@ -25,6 +25,7 @@ from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from armada.exceptions import chartbuilder_exceptions
|
from armada.exceptions import chartbuilder_exceptions
|
||||||
|
from armada import const
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ class ChartBuilder(object):
|
||||||
|
|
||||||
# store chart schema
|
# store chart schema
|
||||||
self.chart = chart
|
self.chart = chart
|
||||||
|
self.chart_data = chart[const.KEYWORD_DATA]
|
||||||
|
|
||||||
# extract, pull, whatever the chart from its source
|
# extract, pull, whatever the chart from its source
|
||||||
self.source_directory = self.get_source_path()
|
self.source_directory = self.get_source_path()
|
||||||
|
@ -62,7 +64,7 @@ class ChartBuilder(object):
|
||||||
Returns "<source directory>/<subpath>" taken from the "source_dir"
|
Returns "<source directory>/<subpath>" taken from the "source_dir"
|
||||||
property from the chart, or else "" if the property isn't a 2-tuple.
|
property from the chart, or else "" if the property isn't a 2-tuple.
|
||||||
'''
|
'''
|
||||||
source_dir = self.chart.get('source_dir')
|
source_dir = self.chart_data.get('source_dir')
|
||||||
return (os.path.join(*source_dir) if
|
return (os.path.join(*source_dir) if
|
||||||
(source_dir and isinstance(source_dir, (list, tuple)) and
|
(source_dir and isinstance(source_dir, (list, tuple)) and
|
||||||
len(source_dir) == 2) else "")
|
len(source_dir) == 2) else "")
|
||||||
|
@ -206,7 +208,7 @@ class ChartBuilder(object):
|
||||||
Process all files in templates/ as a template to attach to the chart,
|
Process all files in templates/ as a template to attach to the chart,
|
||||||
building a :class:`hapi.chart.template_pb2.Template` object.
|
building a :class:`hapi.chart.template_pb2.Template` object.
|
||||||
'''
|
'''
|
||||||
chart_name = self.chart.get('chart_name')
|
chart_name = self.chart['metadata']['name']
|
||||||
templates = []
|
templates = []
|
||||||
if not os.path.exists(
|
if not os.path.exists(
|
||||||
os.path.join(self.source_directory, 'templates')):
|
os.path.join(self.source_directory, 'templates')):
|
||||||
|
@ -240,12 +242,11 @@ class ChartBuilder(object):
|
||||||
return self._helm_chart
|
return self._helm_chart
|
||||||
|
|
||||||
dependencies = []
|
dependencies = []
|
||||||
chart_dependencies = self.chart.get('dependencies', [])
|
chart_dependencies = self.chart_data.get('dependencies', [])
|
||||||
chart_name = self.chart.get('chart_name', None)
|
chart_name = self.chart['metadata']['name']
|
||||||
chart_release = self.chart.get('release', None)
|
chart_release = self.chart_data.get('release', None)
|
||||||
for dep in chart_dependencies:
|
for dep_chart in chart_dependencies:
|
||||||
dep_chart = dep.get('chart', {})
|
dep_chart_name = dep_chart['metadata']['name']
|
||||||
dep_chart_name = dep_chart.get('chart_name', None)
|
|
||||||
LOG.info("Building dependency chart %s for release %s.",
|
LOG.info("Building dependency chart %s for release %s.",
|
||||||
dep_chart_name, chart_release)
|
dep_chart_name, chart_release)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -17,6 +17,7 @@ from oslo_log import log as logging
|
||||||
|
|
||||||
from armada import const
|
from armada import const
|
||||||
from armada import exceptions
|
from armada import exceptions
|
||||||
|
from armada.handlers import schema
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -62,10 +63,10 @@ class Manifest(object):
|
||||||
self.manifest = manifests[0] if manifests else None
|
self.manifest = manifests[0] if manifests else None
|
||||||
|
|
||||||
if not all([self.charts, self.groups, self.manifest]):
|
if not all([self.charts, self.groups, self.manifest]):
|
||||||
expected_schemas = [const.DOCUMENT_CHART, const.DOCUMENT_GROUP]
|
expected_schemas = [schema.TYPE_CHART, schema.TYPE_CHARTGROUP]
|
||||||
error = ('Documents must be a list of documents with at least one '
|
error = ('Documents must include at least one of each of {} '
|
||||||
'of each of the following schemas: %s and only one '
|
'and only one {}').format(expected_schemas,
|
||||||
'manifest' % expected_schemas)
|
schema.TYPE_MANIFEST)
|
||||||
LOG.error(error)
|
LOG.error(error)
|
||||||
raise exceptions.ManifestException(details=error)
|
raise exceptions.ManifestException(details=error)
|
||||||
|
|
||||||
|
@ -87,11 +88,14 @@ class Manifest(object):
|
||||||
groups = []
|
groups = []
|
||||||
manifests = []
|
manifests = []
|
||||||
for document in self.documents:
|
for document in self.documents:
|
||||||
if document.get('schema') == const.DOCUMENT_CHART:
|
schema_info = schema.get_schema_info(document.get('schema'))
|
||||||
|
if not schema_info:
|
||||||
|
continue
|
||||||
|
if schema_info.type == schema.TYPE_CHART:
|
||||||
charts.append(document)
|
charts.append(document)
|
||||||
if document.get('schema') == const.DOCUMENT_GROUP:
|
if schema_info.type == schema.TYPE_CHARTGROUP:
|
||||||
groups.append(document)
|
groups.append(document)
|
||||||
if document.get('schema') == const.DOCUMENT_MANIFEST:
|
if schema_info.type == schema.TYPE_MANIFEST:
|
||||||
manifest_name = document.get('metadata', {}).get('name')
|
manifest_name = document.get('metadata', {}).get('name')
|
||||||
if target_manifest:
|
if target_manifest:
|
||||||
if manifest_name == target_manifest:
|
if manifest_name == target_manifest:
|
||||||
|
@ -113,8 +117,8 @@ class Manifest(object):
|
||||||
if chart.get('metadata', {}).get('name') == name:
|
if chart.get('metadata', {}).get('name') == name:
|
||||||
return chart
|
return chart
|
||||||
raise exceptions.BuildChartException(
|
raise exceptions.BuildChartException(
|
||||||
details='Could not build {} named "{}"'.format(
|
details='Could not find {} named "{}"'.format(
|
||||||
const.DOCUMENT_CHART, name))
|
schema.TYPE_CHART, name))
|
||||||
|
|
||||||
def find_chart_group_document(self, name):
|
def find_chart_group_document(self, name):
|
||||||
"""Returns a chart group document with the specified name
|
"""Returns a chart group document with the specified name
|
||||||
|
@ -129,8 +133,8 @@ class Manifest(object):
|
||||||
if group.get('metadata', {}).get('name') == name:
|
if group.get('metadata', {}).get('name') == name:
|
||||||
return group
|
return group
|
||||||
raise exceptions.BuildChartGroupException(
|
raise exceptions.BuildChartGroupException(
|
||||||
details='Could not build {} named "{}"'.format(
|
details='Could not find {} named "{}"'.format(
|
||||||
const.DOCUMENT_GROUP, name))
|
schema.TYPE_CHARTGROUP, name))
|
||||||
|
|
||||||
def build_chart_deps(self, chart):
|
def build_chart_deps(self, chart):
|
||||||
"""Recursively build chart dependencies for ``chart``.
|
"""Recursively build chart dependencies for ``chart``.
|
||||||
|
@ -143,20 +147,19 @@ class Manifest(object):
|
||||||
under ``chart['data']['dependencies']`` could not be found.
|
under ``chart['data']['dependencies']`` could not be found.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
chart_dependencies = chart.get('data', {}).get('dependencies', [])
|
chart_dependencies = chart.get(const.KEYWORD_DATA, {}).get(
|
||||||
|
'dependencies', [])
|
||||||
for iter, dep in enumerate(chart_dependencies):
|
for iter, dep in enumerate(chart_dependencies):
|
||||||
if isinstance(dep, dict):
|
if isinstance(dep, dict):
|
||||||
continue
|
continue
|
||||||
chart_dep = self.find_chart_document(dep)
|
chart_dep = self.find_chart_document(dep)
|
||||||
self.build_chart_deps(chart_dep)
|
self.build_chart_deps(chart_dep)
|
||||||
chart['data']['dependencies'][iter] = {
|
chart[const.KEYWORD_DATA]['dependencies'][iter] = chart_dep
|
||||||
'chart': chart_dep.get('data', {})
|
|
||||||
}
|
|
||||||
except Exception:
|
except Exception:
|
||||||
raise exceptions.ChartDependencyException(
|
raise exceptions.ChartDependencyException(
|
||||||
details="Could not build dependencies for chart {} in {}".
|
details='Could not build dependencies for {} named "{}"'.
|
||||||
format(
|
format(schema.TYPE_CHART,
|
||||||
chart.get('metadata').get('name'), const.DOCUMENT_CHART))
|
chart.get('metadata').get('name')))
|
||||||
else:
|
else:
|
||||||
return chart
|
return chart
|
||||||
|
|
||||||
|
@ -173,19 +176,19 @@ class Manifest(object):
|
||||||
try:
|
try:
|
||||||
chart = None
|
chart = None
|
||||||
for iter, chart in enumerate(
|
for iter, chart in enumerate(
|
||||||
chart_group.get('data', {}).get('chart_group', [])):
|
chart_group.get(const.KEYWORD_DATA).get(
|
||||||
|
const.KEYWORD_CHARTS, [])):
|
||||||
if isinstance(chart, dict):
|
if isinstance(chart, dict):
|
||||||
continue
|
continue
|
||||||
chart_dep = self.find_chart_document(chart)
|
chart_object = self.find_chart_document(chart)
|
||||||
self.build_chart_deps(chart_dep)
|
self.build_chart_deps(chart_object)
|
||||||
chart_group['data']['chart_group'][iter] = {
|
chart_group[const.KEYWORD_DATA][const.KEYWORD_CHARTS][iter] = \
|
||||||
'chart': chart_dep.get('data', {})
|
chart_object
|
||||||
}
|
|
||||||
except exceptions.ManifestException:
|
except exceptions.ManifestException:
|
||||||
cg_name = chart_group.get('metadata', {}).get('name')
|
cg_name = chart_group.get('metadata', {}).get('name')
|
||||||
raise exceptions.BuildChartGroupException(
|
raise exceptions.BuildChartGroupException(
|
||||||
details="Could not build chart group {} in {}".format(
|
details='Could not build {} named "{}"'.format(
|
||||||
cg_name, const.DOCUMENT_GROUP))
|
schema.TYPE_CHARTGROUP, cg_name))
|
||||||
|
|
||||||
return chart_group
|
return chart_group
|
||||||
|
|
||||||
|
@ -196,20 +199,18 @@ class Manifest(object):
|
||||||
:returns: The Armada manifest with the data of the chart groups.
|
:returns: The Armada manifest with the data of the chart groups.
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
:raises ManifestException: If a chart group's data listed
|
:raises ManifestException: If a chart group's data listed
|
||||||
under ``chart_group['data']`` could not be found.
|
under ``chart_group[const.KEYWORD_DATA]`` could not be found.
|
||||||
"""
|
"""
|
||||||
for iter, group in enumerate(
|
for iter, group in enumerate(
|
||||||
self.manifest.get('data', {}).get('chart_groups', [])):
|
self.manifest.get(const.KEYWORD_DATA, {}).get(
|
||||||
|
const.KEYWORD_GROUPS, [])):
|
||||||
if isinstance(group, dict):
|
if isinstance(group, dict):
|
||||||
continue
|
continue
|
||||||
chart_grp = self.find_chart_group_document(group)
|
chart_grp = self.find_chart_group_document(group)
|
||||||
self.build_chart_group(chart_grp)
|
self.build_chart_group(chart_grp)
|
||||||
|
|
||||||
# Add name to chart group
|
self.manifest[const.KEYWORD_DATA][const.KEYWORD_GROUPS][iter] = \
|
||||||
ch_grp_data = chart_grp.get('data', {})
|
chart_grp
|
||||||
ch_grp_data['name'] = chart_grp.get('metadata', {}).get('name')
|
|
||||||
|
|
||||||
self.manifest['data']['chart_groups'][iter] = ch_grp_data
|
|
||||||
|
|
||||||
return self.manifest
|
return self.manifest
|
||||||
|
|
||||||
|
@ -221,4 +222,4 @@ class Manifest(object):
|
||||||
"""
|
"""
|
||||||
self.build_armada_manifest()
|
self.build_armada_manifest()
|
||||||
|
|
||||||
return {'armada': self.manifest.get('data', {})}
|
return self.manifest
|
||||||
|
|
|
@ -16,9 +16,9 @@ import collections
|
||||||
import json
|
import json
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from armada import const
|
|
||||||
from armada.exceptions import override_exceptions
|
from armada.exceptions import override_exceptions
|
||||||
from armada.exceptions import validate_exceptions
|
from armada.exceptions import validate_exceptions
|
||||||
|
from armada.handlers import schema
|
||||||
from armada.utils import validate
|
from armada.utils import validate
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,17 +65,18 @@ class Override(object):
|
||||||
|
|
||||||
def find_document_type(self, alias):
|
def find_document_type(self, alias):
|
||||||
if alias == 'chart_group':
|
if alias == 'chart_group':
|
||||||
return const.DOCUMENT_GROUP
|
return schema.TYPE_CHARTGROUP
|
||||||
if alias == 'chart':
|
if alias == 'chart':
|
||||||
return const.DOCUMENT_CHART
|
return schema.TYPE_CHART
|
||||||
if alias == 'manifest':
|
if alias == 'manifest':
|
||||||
return const.DOCUMENT_MANIFEST
|
return schema.TYPE_MANIFEST
|
||||||
else:
|
else:
|
||||||
raise ValueError("Could not find {} document".format(alias))
|
raise ValueError("Could not find {} document".format(alias))
|
||||||
|
|
||||||
def find_manifest_document(self, doc_path):
|
def find_manifest_document(self, doc_path):
|
||||||
for doc in self.documents:
|
for doc in self.documents:
|
||||||
if doc.get('schema') == self.find_document_type(
|
schema_info = schema.get_schema_info(doc.get('schema'))
|
||||||
|
if schema_info.type == self.find_document_type(
|
||||||
doc_path[0]) and doc.get('metadata',
|
doc_path[0]) and doc.get('metadata',
|
||||||
{}).get('name') == doc_path[1]:
|
{}).get('name') == doc_path[1]:
|
||||||
return doc
|
return doc
|
||||||
|
@ -121,45 +122,29 @@ class Override(object):
|
||||||
new_data = self.array_to_dict(data_path, new_value)
|
new_data = self.array_to_dict(data_path, new_value)
|
||||||
self.update(document.get('data', {}), new_data)
|
self.update(document.get('data', {}), new_data)
|
||||||
|
|
||||||
def update_document(self, merging_values):
|
def update_documents(self, merging_values):
|
||||||
for doc in merging_values:
|
for doc in merging_values:
|
||||||
if doc.get('schema') == const.DOCUMENT_CHART:
|
self.update_document(doc)
|
||||||
self.update_chart_document(doc)
|
|
||||||
if doc.get('schema') == const.DOCUMENT_GROUP:
|
|
||||||
self.update_chart_group_document(doc)
|
|
||||||
if doc.get('schema') == const.DOCUMENT_MANIFEST:
|
|
||||||
self.update_armada_manifest(doc)
|
|
||||||
|
|
||||||
def update_chart_document(self, ovr):
|
def update_document(self, ovr):
|
||||||
for doc in self.documents:
|
ovr_schema_info = schema.get_schema_info(ovr.get('schema'))
|
||||||
if doc.get('schema') == const.DOCUMENT_CHART and doc.get(
|
if ovr_schema_info:
|
||||||
'metadata', {}).get('name') == ovr.get('metadata',
|
for doc in self.documents:
|
||||||
{}).get('name'):
|
schema_info = schema.get_schema_info(doc.get('schema'))
|
||||||
self.update(doc.get('data', {}), ovr.get('data', {}))
|
if schema_info:
|
||||||
return
|
if schema_info == ovr_schema_info:
|
||||||
|
if doc['metadata']['name'] == ovr['metadata']['name']:
|
||||||
def update_chart_group_document(self, ovr):
|
data = doc.get('data', {})
|
||||||
for doc in self.documents:
|
ovr_data = ovr.get('data', {})
|
||||||
if doc.get('schema') == const.DOCUMENT_GROUP and doc.get(
|
self.update(data, ovr_data)
|
||||||
'metadata', {}).get('name') == ovr.get('metadata',
|
return
|
||||||
{}).get('name'):
|
|
||||||
self.update(doc.get('data', {}), ovr.get('data', {}))
|
|
||||||
return
|
|
||||||
|
|
||||||
def update_armada_manifest(self, ovr):
|
|
||||||
for doc in self.documents:
|
|
||||||
if doc.get('schema') == const.DOCUMENT_MANIFEST and doc.get(
|
|
||||||
'metadata', {}).get('name') == ovr.get('metadata',
|
|
||||||
{}).get('name'):
|
|
||||||
self.update(doc.get('data', {}), ovr.get('data', {}))
|
|
||||||
return
|
|
||||||
|
|
||||||
def update_manifests(self):
|
def update_manifests(self):
|
||||||
|
|
||||||
if self.values:
|
if self.values:
|
||||||
for value in self.values:
|
for value in self.values:
|
||||||
merging_values = self._load_yaml_file(value)
|
merging_values = self._load_yaml_file(value)
|
||||||
self.update_document(merging_values)
|
self.update_documents(merging_values)
|
||||||
# Validate document with updated values
|
# Validate document with updated values
|
||||||
self._document_checker(self.documents, self.values)
|
self._document_checker(self.documents, self.values)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Copyright 2019 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
|
||||||
|
import pkg_resources
|
||||||
|
import re
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
# Types
|
||||||
|
TYPE_CHART = 'Chart'
|
||||||
|
TYPE_CHARTGROUP = 'ChartGroup'
|
||||||
|
TYPE_MANIFEST = 'Manifest'
|
||||||
|
|
||||||
|
# Versions
|
||||||
|
VERSION_FORMAT = r'^v(\d+)$'
|
||||||
|
VERSION_MIN = 1
|
||||||
|
VERSION_MAX = 2
|
||||||
|
|
||||||
|
# Creates a mapping between ``metadata.name``: ``data`` where the
|
||||||
|
# ``metadata.name`` is the ``schema`` of a manifest and the ``data`` is the
|
||||||
|
# JSON schema to be used to validate the manifest in question.
|
||||||
|
_SCHEMAS = {}
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaInfo(object):
|
||||||
|
|
||||||
|
def __init__(self, type, version, data):
|
||||||
|
self.type = type
|
||||||
|
self.version = version
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.type == other.type and self.version == other.version
|
||||||
|
|
||||||
|
|
||||||
|
def get_schema_info(name):
|
||||||
|
return _SCHEMAS.get(name)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_schema_info(name, data):
|
||||||
|
parts = name.split('/')
|
||||||
|
prefix, type, version_string = parts
|
||||||
|
version_match = re.search(VERSION_FORMAT, version_string)
|
||||||
|
version = int(version_match.group(1))
|
||||||
|
return SchemaInfo(type, version, data)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_schema_dir():
|
||||||
|
return pkg_resources.resource_filename('armada', 'schemas')
|
||||||
|
|
||||||
|
|
||||||
|
def _load_schemas():
|
||||||
|
"""Populates ``_SCHEMAS`` with the schemas defined in package
|
||||||
|
``armada.schemas``.
|
||||||
|
|
||||||
|
"""
|
||||||
|
schema_dir = _get_schema_dir()
|
||||||
|
for schema_file in os.listdir(schema_dir):
|
||||||
|
with open(os.path.join(schema_dir, schema_file)) as f:
|
||||||
|
for schema in yaml.safe_load_all(f):
|
||||||
|
name = schema['metadata']['name']
|
||||||
|
if name in _SCHEMAS:
|
||||||
|
raise RuntimeError(
|
||||||
|
'Duplicate schema specified for: %s.' % name)
|
||||||
|
_SCHEMAS[name] = _get_schema_info(name, schema['data'])
|
||||||
|
|
||||||
|
|
||||||
|
# Fill the cache.
|
||||||
|
_load_schemas()
|
|
@ -60,9 +60,7 @@ class Test(object):
|
||||||
|
|
||||||
self.timeout = const.DEFAULT_TEST_TIMEOUT
|
self.timeout = const.DEFAULT_TEST_TIMEOUT
|
||||||
|
|
||||||
# NOTE(drewwalters96): Support the chart_group `test_charts` key until
|
# TODO: Remove when v1 doc support is removed.
|
||||||
# its deprecation period ends. The `test.enabled`, `enable_all` flag,
|
|
||||||
# and deprecated, boolean `test` key override this value if provided.
|
|
||||||
if cg_test_charts is not None:
|
if cg_test_charts is not None:
|
||||||
LOG.warn('Chart group key `test_charts` is deprecated and will be '
|
LOG.warn('Chart group key `test_charts` is deprecated and will be '
|
||||||
'removed. Use `test.enabled` instead.')
|
'removed. Use `test.enabled` instead.')
|
||||||
|
@ -70,7 +68,7 @@ class Test(object):
|
||||||
else:
|
else:
|
||||||
self.test_enabled = True
|
self.test_enabled = True
|
||||||
|
|
||||||
# NOTE: Support old, boolean `test` key until deprecation period ends.
|
# TODO: Remove when v1 doc support is removed.
|
||||||
if (type(test_values) == bool):
|
if (type(test_values) == bool):
|
||||||
LOG.warn('Boolean value for chart `test` key is deprecated and '
|
LOG.warn('Boolean value for chart `test` key is deprecated and '
|
||||||
'will be removed. Use `test.enabled` instead.')
|
'will be removed. Use `test.enabled` instead.')
|
||||||
|
|
|
@ -30,8 +30,10 @@ from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from armada import const
|
from armada import const
|
||||||
|
from armada.conf import get_current_chart
|
||||||
from armada.exceptions import tiller_exceptions as ex
|
from armada.exceptions import tiller_exceptions as ex
|
||||||
from armada.handlers.k8s import K8s
|
from armada.handlers.k8s import K8s
|
||||||
|
from armada.handlers import schema
|
||||||
from armada.utils import helm
|
from armada.utils import helm
|
||||||
from armada.utils.release import label_selectors, get_release_status
|
from armada.utils.release import label_selectors, get_release_status
|
||||||
|
|
||||||
|
@ -303,6 +305,7 @@ class Tiller(object):
|
||||||
:param namespace: name of pod for actions
|
:param namespace: name of pod for actions
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# TODO: Remove when v1 doc support is removed.
|
||||||
try:
|
try:
|
||||||
for action in actions.get('update', []):
|
for action in actions.get('update', []):
|
||||||
name = action.get('name')
|
name = action.get('name')
|
||||||
|
@ -667,15 +670,20 @@ class Tiller(object):
|
||||||
self.k8s.delete_job_action(jb_name, namespace, timeout=timeout)
|
self.k8s.delete_job_action(jb_name, namespace, timeout=timeout)
|
||||||
handled = True
|
handled = True
|
||||||
|
|
||||||
if resource_type == 'cronjob' or resource_type == 'job':
|
# TODO: Remove when v1 doc support is removed.
|
||||||
|
chart = get_current_chart()
|
||||||
|
schema_info = schema.get_schema_info(chart['schema'])
|
||||||
|
job_implies_cronjob = schema_info.version < 2
|
||||||
|
implied_cronjob = resource_type == 'job' and job_implies_cronjob
|
||||||
|
|
||||||
|
if resource_type == 'cronjob' or implied_cronjob:
|
||||||
get_jobs = self.k8s.get_namespace_cron_job(
|
get_jobs = self.k8s.get_namespace_cron_job(
|
||||||
namespace, label_selector=label_selector)
|
namespace, label_selector=label_selector)
|
||||||
for jb in get_jobs.items:
|
for jb in get_jobs.items:
|
||||||
jb_name = jb.metadata.name
|
jb_name = jb.metadata.name
|
||||||
|
|
||||||
if resource_type == 'job':
|
# TODO: Remove when v1 doc support is removed.
|
||||||
# TODO: Eventually disallow this, allowing initially since
|
if implied_cronjob:
|
||||||
# some existing clients were expecting this behavior.
|
|
||||||
LOG.warn("Deleting cronjobs via `type: job` is "
|
LOG.warn("Deleting cronjobs via `type: job` is "
|
||||||
"deprecated, use `type: cronjob` instead")
|
"deprecated, use `type: cronjob` instead")
|
||||||
|
|
||||||
|
@ -726,7 +734,7 @@ class Tiller(object):
|
||||||
values,
|
values,
|
||||||
timeout=const.DEFAULT_TILLER_TIMEOUT):
|
timeout=const.DEFAULT_TILLER_TIMEOUT):
|
||||||
'''
|
'''
|
||||||
update statefullsets (daemon, stateful)
|
update statefulsets (daemon, stateful)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if action_type == 'daemonset':
|
if action_type == 'daemonset':
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# JSON schema for validating Armada charts.
|
# NOTE: Do not modify this schema, it is deprecated.
|
||||||
---
|
---
|
||||||
schema: deckhand/DataSchema/v1
|
schema: deckhand/DataSchema/v1
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -60,7 +60,6 @@ data:
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
test:
|
test:
|
||||||
anyOf:
|
anyOf:
|
||||||
# TODO: Remove boolean support after deprecation period.
|
|
||||||
- type: boolean
|
- type: boolean
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -75,7 +74,6 @@ data:
|
||||||
type: boolean
|
type: boolean
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
# TODO(MarshM): Deprecate this `timeout` in favor of `wait.timeout`
|
|
||||||
timeout:
|
timeout:
|
||||||
type: integer
|
type: integer
|
||||||
wait:
|
wait:
|
||||||
|
@ -153,8 +151,6 @@ data:
|
||||||
$ref: '#/definitions/hook_action'
|
$ref: '#/definitions/hook_action'
|
||||||
create:
|
create:
|
||||||
$ref: '#/definitions/hook_action'
|
$ref: '#/definitions/hook_action'
|
||||||
# TODO(drewwalters96): Armada ignores post-update actions. Remove them
|
|
||||||
# in future schemas.
|
|
||||||
post:
|
post:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
|
@ -0,0 +1,151 @@
|
||||||
|
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# JSON schema for validating Armada charts.
|
||||||
|
---
|
||||||
|
schema: deckhand/DataSchema/v1
|
||||||
|
metadata:
|
||||||
|
name: armada/Chart/v2
|
||||||
|
schema: metadata/Control/v1
|
||||||
|
data:
|
||||||
|
$schema: http://json-schema.org/schema#
|
||||||
|
definitions:
|
||||||
|
labels:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
hook_action:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
labels:
|
||||||
|
$ref: '#/definitions/labels'
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
additionalProperties: false
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
release:
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
values:
|
||||||
|
type: object
|
||||||
|
# TODO: Remove this, and just read dependencies out of `chart` dir as helm
|
||||||
|
# CLI does.
|
||||||
|
dependencies:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
protected:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
continue_processing:
|
||||||
|
type: boolean
|
||||||
|
additionalProperties: false
|
||||||
|
test:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
timeout:
|
||||||
|
type: integer
|
||||||
|
options:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
cleanup:
|
||||||
|
type: boolean
|
||||||
|
additionalProperties: false
|
||||||
|
additionalProperties: false
|
||||||
|
wait:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
timeout:
|
||||||
|
type: integer
|
||||||
|
resources:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
labels:
|
||||||
|
$ref: '#/definitions/labels'
|
||||||
|
min_ready:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
additionalProperties: false
|
||||||
|
labels:
|
||||||
|
$ref: "#/definitions/labels"
|
||||||
|
# Config for helm's native `--wait` param.
|
||||||
|
native:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
additionalProperties: false
|
||||||
|
additionalProperties: false
|
||||||
|
source:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
location:
|
||||||
|
type: string
|
||||||
|
subpath:
|
||||||
|
type: string
|
||||||
|
reference:
|
||||||
|
type: string
|
||||||
|
proxy_server:
|
||||||
|
type: string
|
||||||
|
auth_method:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- location
|
||||||
|
- type
|
||||||
|
delete:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
timeout:
|
||||||
|
type: integer
|
||||||
|
upgrade:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
no_hooks:
|
||||||
|
type: boolean
|
||||||
|
pre:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
delete:
|
||||||
|
$ref: '#/definitions/hook_action'
|
||||||
|
options:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
force:
|
||||||
|
type: boolean
|
||||||
|
recreate_pods:
|
||||||
|
type: boolean
|
||||||
|
additionalProperties: false
|
||||||
|
additionalProperties: false
|
||||||
|
required:
|
||||||
|
- namespace
|
||||||
|
- release
|
||||||
|
- source
|
||||||
|
additionalProperties: false
|
||||||
|
...
|
|
@ -12,7 +12,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# JSON schema for validating Armada chart groups.
|
# NOTE: Do not modify this schema, it is deprecated.
|
||||||
---
|
---
|
||||||
schema: deckhand/DataSchema/v1
|
schema: deckhand/DataSchema/v1
|
||||||
metadata:
|
metadata:
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# JSON schema for validating Armada chart groups.
|
||||||
|
---
|
||||||
|
schema: deckhand/DataSchema/v1
|
||||||
|
metadata:
|
||||||
|
name: armada/ChartGroup/v2
|
||||||
|
schema: metadata/Control/v1
|
||||||
|
data:
|
||||||
|
$schema: http://json-schema.org/schema#
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
sequenced:
|
||||||
|
type: boolean
|
||||||
|
chart_group:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
# TODO: Rename to `charts`?
|
||||||
|
- chart_group
|
||||||
|
additionalProperties: false
|
||||||
|
...
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# NOTE: Do not modify this schema, it is deprecated.
|
||||||
|
---
|
||||||
|
schema: deckhand/DataSchema/v1
|
||||||
|
metadata:
|
||||||
|
name: armada/Manifest/v1
|
||||||
|
schema: metadata/Control/v1
|
||||||
|
data:
|
||||||
|
$schema: http://json-schema.org/schema#
|
||||||
|
properties:
|
||||||
|
release_prefix:
|
||||||
|
type: string
|
||||||
|
chart_groups:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- chart_groups
|
||||||
|
- release_prefix
|
||||||
|
additionalProperties: false
|
||||||
|
...
|
|
@ -16,7 +16,7 @@
|
||||||
---
|
---
|
||||||
schema: deckhand/DataSchema/v1
|
schema: deckhand/DataSchema/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: armada/Manifest/v1
|
name: armada/Manifest/v2
|
||||||
schema: metadata/Control/v1
|
schema: metadata/Control/v1
|
||||||
data:
|
data:
|
||||||
$schema: http://json-schema.org/schema#
|
$schema: http://json-schema.org/schema#
|
|
@ -169,8 +169,7 @@ class TestReleasesManifestControllerNegativeTest(base.BaseControllerTest):
|
||||||
self.assertIn({
|
self.assertIn({
|
||||||
'message':
|
'message':
|
||||||
('An error occurred while building chart group: '
|
('An error occurred while building chart group: '
|
||||||
'Could not build chart group keystone-infra-services in '
|
'Could not build ChartGroup named "keystone-infra-services".'),
|
||||||
'armada/ChartGroup/v1.'),
|
|
||||||
'error':
|
'error':
|
||||||
True,
|
True,
|
||||||
'kind':
|
'kind':
|
||||||
|
|
|
@ -158,125 +158,153 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
armada_obj.pre_flight_ops()
|
armada_obj.pre_flight_ops()
|
||||||
|
|
||||||
expected_config = {
|
expected_config = {
|
||||||
'armada': {
|
'schema': 'armada/Manifest/v1',
|
||||||
'release_prefix':
|
'metadata': {
|
||||||
'armada',
|
'schema': 'metadata/Document/v1',
|
||||||
|
'name': 'example-manifest'
|
||||||
|
},
|
||||||
|
'data': {
|
||||||
|
'release_prefix': 'armada',
|
||||||
'chart_groups': [{
|
'chart_groups': [{
|
||||||
'chart_group': [{
|
'schema': 'armada/ChartGroup/v1',
|
||||||
'chart': {
|
'metadata': {
|
||||||
'dependencies': [],
|
'schema': 'metadata/Document/v1',
|
||||||
'chart_name': 'test_chart_1',
|
'name': 'example-group'
|
||||||
'namespace': 'test',
|
},
|
||||||
'release': 'test_chart_1',
|
'data': {
|
||||||
'source': {
|
'chart_group': [{
|
||||||
'location': ('git://github.com/dummy/armada'),
|
'schema': 'armada/Chart/v1',
|
||||||
'reference': 'master',
|
'metadata': {
|
||||||
'subpath': 'chart_1',
|
'schema': 'metadata/Document/v1',
|
||||||
'type': 'git'
|
'name': 'example-chart-1'
|
||||||
},
|
},
|
||||||
'source_dir': CHART_SOURCES[0],
|
'data': {
|
||||||
'values': {},
|
'dependencies': [],
|
||||||
'wait': {
|
'chart_name': 'test_chart_1',
|
||||||
'timeout': 10,
|
'namespace': 'test',
|
||||||
'native': {
|
'release': 'test_chart_1',
|
||||||
'enabled': False
|
'source': {
|
||||||
}
|
'location':
|
||||||
},
|
'git://github.com/dummy/armada',
|
||||||
'test': {
|
'reference': 'master',
|
||||||
'enabled': True
|
'subpath': 'chart_1',
|
||||||
}
|
'type': 'git'
|
||||||
}
|
},
|
||||||
}, {
|
'source_dir': CHART_SOURCES[0],
|
||||||
'chart': {
|
'values': {},
|
||||||
'dependencies': [],
|
'wait': {
|
||||||
'chart_name': 'test_chart_2',
|
'timeout': 10,
|
||||||
'namespace': 'test',
|
'native': {
|
||||||
'protected': {
|
'enabled': False
|
||||||
'continue_processing': True
|
}
|
||||||
},
|
},
|
||||||
'release': 'test_chart_2',
|
'test': {
|
||||||
'source': {
|
'enabled': True
|
||||||
'location': '/tmp/dummy/armada',
|
|
||||||
'subpath': 'chart_2',
|
|
||||||
'type': 'local'
|
|
||||||
},
|
|
||||||
'source_dir': CHART_SOURCES[1],
|
|
||||||
'values': {},
|
|
||||||
'wait': {
|
|
||||||
'timeout': 10
|
|
||||||
},
|
|
||||||
'upgrade': {
|
|
||||||
'no_hooks': False,
|
|
||||||
'options': {
|
|
||||||
'force': True,
|
|
||||||
'recreate_pods': True
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'test': {
|
|
||||||
'enabled': True,
|
|
||||||
'options': {
|
|
||||||
'cleanup': True
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}, {
|
||||||
}, {
|
'schema': 'armada/Chart/v1',
|
||||||
'chart': {
|
'metadata': {
|
||||||
'dependencies': [],
|
'schema': 'metadata/Document/v1',
|
||||||
'chart_name': 'test_chart_3',
|
'name': 'example-chart-2'
|
||||||
'namespace': 'test',
|
|
||||||
'protected': {
|
|
||||||
'continue_processing': False
|
|
||||||
},
|
},
|
||||||
'release': 'test_chart_3',
|
'data': {
|
||||||
'source': {
|
'dependencies': [],
|
||||||
'location': '/tmp/dummy/armada',
|
'chart_name': 'test_chart_2',
|
||||||
'subpath': 'chart_3',
|
'namespace': 'test',
|
||||||
'type': 'local'
|
'protected': {
|
||||||
},
|
'continue_processing': True
|
||||||
'source_dir': CHART_SOURCES[2],
|
},
|
||||||
'values': {},
|
'release': 'test_chart_2',
|
||||||
'wait': {
|
'source': {
|
||||||
'timeout': 10
|
'location': '/tmp/dummy/armada',
|
||||||
},
|
'subpath': 'chart_2',
|
||||||
'upgrade': {
|
'type': 'local'
|
||||||
'no_hooks': False
|
},
|
||||||
|
'source_dir': CHART_SOURCES[1],
|
||||||
|
'values': {},
|
||||||
|
'wait': {
|
||||||
|
'timeout': 10
|
||||||
|
},
|
||||||
|
'upgrade': {
|
||||||
|
'no_hooks': False,
|
||||||
|
'options': {
|
||||||
|
'force': True,
|
||||||
|
'recreate_pods': True
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'test': {
|
||||||
|
'enabled': True,
|
||||||
|
'options': {
|
||||||
|
'cleanup': True
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}, {
|
||||||
}, {
|
'schema': 'armada/Chart/v1',
|
||||||
'chart': {
|
'metadata': {
|
||||||
'dependencies': [],
|
'schema': 'metadata/Document/v1',
|
||||||
'chart_name': 'test_chart_4',
|
'name': 'example-chart-3'
|
||||||
'namespace': 'test',
|
|
||||||
'release': 'test_chart_4',
|
|
||||||
'source': {
|
|
||||||
'location': '/tmp/dummy/armada',
|
|
||||||
'subpath': 'chart_4',
|
|
||||||
'type': 'local'
|
|
||||||
},
|
},
|
||||||
'source_dir': CHART_SOURCES[3],
|
'data': {
|
||||||
'values': {},
|
'dependencies': [],
|
||||||
'wait': {
|
'chart_name': 'test_chart_3',
|
||||||
'timeout': 10
|
'namespace': 'test',
|
||||||
|
'protected': {
|
||||||
|
'continue_processing': False
|
||||||
|
},
|
||||||
|
'release': 'test_chart_3',
|
||||||
|
'source': {
|
||||||
|
'location': '/tmp/dummy/armada',
|
||||||
|
'subpath': 'chart_3',
|
||||||
|
'type': 'local'
|
||||||
|
},
|
||||||
|
'source_dir': CHART_SOURCES[2],
|
||||||
|
'values': {},
|
||||||
|
'wait': {
|
||||||
|
'timeout': 10
|
||||||
|
},
|
||||||
|
'upgrade': {
|
||||||
|
'no_hooks': False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'schema': 'armada/Chart/v1',
|
||||||
|
'metadata': {
|
||||||
|
'schema': 'metadata/Document/v1',
|
||||||
|
'name': 'example-chart-4'
|
||||||
},
|
},
|
||||||
'upgrade': {
|
'data': {
|
||||||
'no_hooks': False
|
'dependencies': [],
|
||||||
},
|
'chart_name': 'test_chart_4',
|
||||||
'test': True
|
'namespace': 'test',
|
||||||
}
|
'release': 'test_chart_4',
|
||||||
}],
|
'source': {
|
||||||
'description':
|
'location': '/tmp/dummy/armada',
|
||||||
'this is a test',
|
'subpath': 'chart_4',
|
||||||
'name':
|
'type': 'local'
|
||||||
'example-group',
|
},
|
||||||
'sequenced':
|
'source_dir': CHART_SOURCES[3],
|
||||||
True
|
'values': {},
|
||||||
|
'wait': {
|
||||||
|
'timeout': 10
|
||||||
|
},
|
||||||
|
'upgrade': {
|
||||||
|
'no_hooks': False
|
||||||
|
},
|
||||||
|
'test': True
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
'description': 'this is a test',
|
||||||
|
'sequenced': True
|
||||||
|
}
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
} # yapf: disable
|
} # yapf: disable
|
||||||
|
|
||||||
self.assertTrue(hasattr(armada_obj, 'manifest'))
|
self.assertTrue(hasattr(armada_obj, 'manifest'))
|
||||||
self.assertIsInstance(armada_obj.manifest, dict)
|
self.assertIsInstance(armada_obj.manifest, dict)
|
||||||
self.assertIn('armada', armada_obj.manifest)
|
self.assertIn('data', armada_obj.manifest)
|
||||||
self.assertEqual(expected_config, armada_obj.manifest)
|
self.assertEqual(expected_config, armada_obj.manifest)
|
||||||
|
|
||||||
@mock.patch.object(armada, 'source')
|
@mock.patch.object(armada, 'source')
|
||||||
|
@ -314,9 +342,11 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
|
|
||||||
armada_obj.post_flight_ops()
|
armada_obj.post_flight_ops()
|
||||||
|
|
||||||
for group in armada_obj.manifest['armada']['chart_groups']:
|
for group in armada_obj.manifest['data']['chart_groups']:
|
||||||
for counter, chart in enumerate(group.get('chart_group')):
|
for counter, chart in enumerate(
|
||||||
if chart.get('chart').get('source').get('type') == 'git':
|
group.get(const.KEYWORD_DATA).get(const.KEYWORD_CHARTS)):
|
||||||
|
if chart.get(
|
||||||
|
const.KEYWORD_DATA).get('source').get('type') == 'git':
|
||||||
mock_source.source_cleanup.assert_called_with(
|
mock_source.source_cleanup.assert_called_with(
|
||||||
CHART_SOURCES[counter][0])
|
CHART_SOURCES[counter][0])
|
||||||
|
|
||||||
|
@ -348,7 +378,8 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
armada_obj = armada.Armada(yaml_documents, m_tiller)
|
armada_obj = armada.Armada(yaml_documents, m_tiller)
|
||||||
armada_obj.chart_deploy.get_diff = mock.Mock()
|
armada_obj.chart_deploy.get_diff = mock.Mock()
|
||||||
|
|
||||||
chart_group = armada_obj.manifest['armada']['chart_groups'][0]
|
cg = armada_obj.manifest['data']['chart_groups'][0]
|
||||||
|
chart_group = cg['data']
|
||||||
charts = chart_group['chart_group']
|
charts = chart_group['chart_group']
|
||||||
cg_test_all_charts = chart_group.get('test_charts')
|
cg_test_all_charts = chart_group.get('test_charts')
|
||||||
|
|
||||||
|
@ -380,9 +411,9 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
expected_test_constructor_calls = []
|
expected_test_constructor_calls = []
|
||||||
|
|
||||||
for c in charts:
|
for c in charts:
|
||||||
chart = c['chart']
|
chart = c['data']
|
||||||
release = chart['release']
|
release = chart['release']
|
||||||
prefix = armada_obj.manifest['armada']['release_prefix']
|
prefix = armada_obj.manifest['data']['release_prefix']
|
||||||
release_name = release_prefixer(prefix, release)
|
release_name = release_prefixer(prefix, release)
|
||||||
# Simplified check because the actual code uses logical-or's
|
# Simplified check because the actual code uses logical-or's
|
||||||
# multiple conditions, so this is enough.
|
# multiple conditions, so this is enough.
|
||||||
|
@ -394,8 +425,8 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
mock.call(
|
mock.call(
|
||||||
mock_chartbuilder().get_helm_chart(),
|
mock_chartbuilder().get_helm_chart(),
|
||||||
"{}-{}".format(
|
"{}-{}".format(
|
||||||
armada_obj.manifest['armada']
|
armada_obj.manifest['data']['release_prefix'],
|
||||||
['release_prefix'], chart['release']),
|
chart['release']),
|
||||||
chart['namespace'],
|
chart['namespace'],
|
||||||
values=yaml.safe_dump(chart['values']),
|
values=yaml.safe_dump(chart['values']),
|
||||||
wait=native_wait_enabled,
|
wait=native_wait_enabled,
|
||||||
|
@ -420,7 +451,7 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
mock.call(
|
mock.call(
|
||||||
mock_chartbuilder().get_helm_chart(),
|
mock_chartbuilder().get_helm_chart(),
|
||||||
"{}-{}".format(
|
"{}-{}".format(
|
||||||
armada_obj.manifest['armada']
|
armada_obj.manifest['data']
|
||||||
['release_prefix'],
|
['release_prefix'],
|
||||||
chart['release']),
|
chart['release']),
|
||||||
chart['namespace'],
|
chart['namespace'],
|
||||||
|
@ -449,7 +480,7 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||||
mock.call(
|
mock.call(
|
||||||
mock_chartbuilder().get_helm_chart(),
|
mock_chartbuilder().get_helm_chart(),
|
||||||
"{}-{}".format(
|
"{}-{}".format(
|
||||||
armada_obj.manifest['armada']
|
armada_obj.manifest['data']
|
||||||
['release_prefix'],
|
['release_prefix'],
|
||||||
chart['release']),
|
chart['release']),
|
||||||
chart['namespace'],
|
chart['namespace'],
|
||||||
|
@ -647,8 +678,8 @@ class ArmadaNegativeHandlerTestCase(base.ArmadaTestCase):
|
||||||
def test_armada_get_manifest_exception(self, mock_source):
|
def test_armada_get_manifest_exception(self, mock_source):
|
||||||
"""Test armada handling with invalid manifest."""
|
"""Test armada handling with invalid manifest."""
|
||||||
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
||||||
error_re = ('Documents must be a list of documents with at least one '
|
error_re = ('.*Documents must include at least one of each of .* and '
|
||||||
'of each of the following schemas: .*')
|
'only one .*')
|
||||||
self.assertRaisesRegexp(ManifestException, error_re, armada.Armada,
|
self.assertRaisesRegexp(ManifestException, error_re, armada.Armada,
|
||||||
yaml_documents[:1], mock.MagicMock())
|
yaml_documents[:1], mock.MagicMock())
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ from hapi.chart.metadata_pb2 import Metadata
|
||||||
import mock
|
import mock
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from armada import const
|
||||||
from armada.handlers.chartbuilder import ChartBuilder
|
from armada.handlers.chartbuilder import ChartBuilder
|
||||||
from armada.exceptions import chartbuilder_exceptions
|
from armada.exceptions import chartbuilder_exceptions
|
||||||
|
|
||||||
|
@ -59,7 +60,9 @@ class BaseChartBuilderTestCase(testtools.TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
chart_stream = """
|
chart_stream = """
|
||||||
chart:
|
metadata:
|
||||||
|
name: test
|
||||||
|
data:
|
||||||
chart_name: mariadb
|
chart_name: mariadb
|
||||||
release: mariadb
|
release: mariadb
|
||||||
namespace: openstack
|
namespace: openstack
|
||||||
|
@ -87,7 +90,9 @@ class BaseChartBuilderTestCase(testtools.TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dependency_chart_stream = """
|
dependency_chart_stream = """
|
||||||
chart:
|
metadata:
|
||||||
|
name: dep
|
||||||
|
data:
|
||||||
chart_name: keystone
|
chart_name: keystone
|
||||||
release: keystone
|
release: keystone
|
||||||
namespace: undercloud
|
namespace: undercloud
|
||||||
|
@ -120,6 +125,16 @@ class BaseChartBuilderTestCase(testtools.TestCase):
|
||||||
self.addCleanup(shutil.rmtree, subdir)
|
self.addCleanup(shutil.rmtree, subdir)
|
||||||
return subdir
|
return subdir
|
||||||
|
|
||||||
|
def _get_test_chart(self, chart_dir):
|
||||||
|
return {
|
||||||
|
'metadata': {
|
||||||
|
'name': 'test'
|
||||||
|
},
|
||||||
|
const.KEYWORD_DATA: {
|
||||||
|
'source_dir': (chart_dir.path, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
|
|
||||||
|
@ -131,8 +146,7 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
||||||
self.chart_yaml)
|
self.chart_yaml)
|
||||||
|
|
||||||
test_chart = {'source_dir': (chart_dir.path, '')}
|
chartbuilder = ChartBuilder(self._get_test_chart(chart_dir))
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
|
||||||
|
|
||||||
# Validate response type is :class:`hapi.chart.metadata_pb2.Metadata`
|
# Validate response type is :class:`hapi.chart.metadata_pb2.Metadata`
|
||||||
resp = chartbuilder.get_metadata()
|
resp = chartbuilder.get_metadata()
|
||||||
|
@ -142,8 +156,7 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
chart_dir = self.useFixture(fixtures.TempDir())
|
chart_dir = self.useFixture(fixtures.TempDir())
|
||||||
self.addCleanup(shutil.rmtree, chart_dir.path)
|
self.addCleanup(shutil.rmtree, chart_dir.path)
|
||||||
|
|
||||||
test_chart = {'source_dir': (chart_dir.path, '')}
|
chartbuilder = ChartBuilder(self._get_test_chart(chart_dir))
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
|
||||||
|
|
||||||
self.assertRaises(chartbuilder_exceptions.MetadataLoadException,
|
self.assertRaises(chartbuilder_exceptions.MetadataLoadException,
|
||||||
chartbuilder.get_metadata)
|
chartbuilder.get_metadata)
|
||||||
|
@ -168,8 +181,7 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
for filename in ['template%d' % x for x in range(3)]:
|
for filename in ['template%d' % x for x in range(3)]:
|
||||||
self._write_temporary_file_contents(templates_subdir, filename, "")
|
self._write_temporary_file_contents(templates_subdir, filename, "")
|
||||||
|
|
||||||
test_chart = {'source_dir': (chart_dir.path, '')}
|
chartbuilder = ChartBuilder(self._get_test_chart(chart_dir))
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
|
||||||
|
|
||||||
expected_files = (
|
expected_files = (
|
||||||
'[type_url: "%s"\n, type_url: "%s"\n]' % ('./bar', './foo'))
|
'[type_url: "%s"\n, type_url: "%s"\n]' % ('./bar', './foo'))
|
||||||
|
@ -185,8 +197,7 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(
|
self._write_temporary_file_contents(
|
||||||
chart_dir.path, filename, "DIRC^@^@^@^B^@^@^@×Z®<86>F.1")
|
chart_dir.path, filename, "DIRC^@^@^@^B^@^@^@×Z®<86>F.1")
|
||||||
|
|
||||||
test_chart = {'source_dir': (chart_dir.path, '')}
|
chartbuilder = ChartBuilder(self._get_test_chart(chart_dir))
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
|
||||||
chartbuilder.get_files()
|
chartbuilder.get_files()
|
||||||
|
|
||||||
def test_get_basic_helm_chart(self):
|
def test_get_basic_helm_chart(self):
|
||||||
|
@ -197,8 +208,8 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self.addCleanup(shutil.rmtree, chart_dir.path)
|
self.addCleanup(shutil.rmtree, chart_dir.path)
|
||||||
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
||||||
self.chart_yaml)
|
self.chart_yaml)
|
||||||
ch = yaml.safe_load(self.chart_stream)['chart']
|
ch = yaml.safe_load(self.chart_stream)
|
||||||
ch['source_dir'] = (chart_dir.path, '')
|
ch['data']['source_dir'] = (chart_dir.path, '')
|
||||||
|
|
||||||
test_chart = ch
|
test_chart = ch
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
chartbuilder = ChartBuilder(test_chart)
|
||||||
|
@ -228,8 +239,8 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(chart_dir.path, 'values.yaml',
|
self._write_temporary_file_contents(chart_dir.path, 'values.yaml',
|
||||||
self.chart_value)
|
self.chart_value)
|
||||||
|
|
||||||
ch = yaml.safe_load(self.chart_stream)['chart']
|
ch = yaml.safe_load(self.chart_stream)
|
||||||
ch['source_dir'] = (chart_dir.path, '')
|
ch['data']['source_dir'] = (chart_dir.path, '')
|
||||||
|
|
||||||
test_chart = ch
|
test_chart = ch
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
chartbuilder = ChartBuilder(test_chart)
|
||||||
|
@ -257,8 +268,8 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
'nested')
|
'nested')
|
||||||
self._write_temporary_file_contents(nested_dir, 'nested0', "random")
|
self._write_temporary_file_contents(nested_dir, 'nested0', "random")
|
||||||
|
|
||||||
ch = yaml.safe_load(self.chart_stream)['chart']
|
ch = yaml.safe_load(self.chart_stream)
|
||||||
ch['source_dir'] = (chart_dir.path, '')
|
ch['data']['source_dir'] = (chart_dir.path, '')
|
||||||
|
|
||||||
test_chart = ch
|
test_chart = ch
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
chartbuilder = ChartBuilder(test_chart)
|
||||||
|
@ -313,8 +324,8 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
# Files to **include** within charts/ subdirectory.
|
# Files to **include** within charts/ subdirectory.
|
||||||
self._write_temporary_file_contents(charts_subdir, '.prov', "xyzzy")
|
self._write_temporary_file_contents(charts_subdir, '.prov', "xyzzy")
|
||||||
|
|
||||||
ch = yaml.safe_load(self.chart_stream)['chart']
|
ch = yaml.safe_load(self.chart_stream)
|
||||||
ch['source_dir'] = (chart_dir.path, '')
|
ch['data']['source_dir'] = (chart_dir.path, '')
|
||||||
|
|
||||||
test_chart = ch
|
test_chart = ch
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
chartbuilder = ChartBuilder(test_chart)
|
||||||
|
@ -340,8 +351,8 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self.addCleanup(shutil.rmtree, chart_dir.path)
|
self.addCleanup(shutil.rmtree, chart_dir.path)
|
||||||
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
||||||
self.chart_yaml)
|
self.chart_yaml)
|
||||||
ch = yaml.safe_load(self.chart_stream)['chart']
|
ch = yaml.safe_load(self.chart_stream)
|
||||||
ch['source_dir'] = (chart_dir.path, '')
|
ch['data']['source_dir'] = (chart_dir.path, '')
|
||||||
|
|
||||||
# Dependency chart directory and files.
|
# Dependency chart directory and files.
|
||||||
dep_chart_dir = self.useFixture(fixtures.TempDir())
|
dep_chart_dir = self.useFixture(fixtures.TempDir())
|
||||||
|
@ -349,11 +360,11 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(dep_chart_dir.path, 'Chart.yaml',
|
self._write_temporary_file_contents(dep_chart_dir.path, 'Chart.yaml',
|
||||||
self.dependency_chart_yaml)
|
self.dependency_chart_yaml)
|
||||||
dep_ch = yaml.safe_load(self.dependency_chart_stream)
|
dep_ch = yaml.safe_load(self.dependency_chart_stream)
|
||||||
dep_ch['chart']['source_dir'] = (dep_chart_dir.path, '')
|
dep_ch['data']['source_dir'] = (dep_chart_dir.path, '')
|
||||||
|
|
||||||
main_chart = ch
|
main_chart = ch
|
||||||
dependency_chart = dep_ch
|
dependency_chart = dep_ch
|
||||||
main_chart['dependencies'] = [dependency_chart]
|
main_chart['data']['dependencies'] = [dependency_chart]
|
||||||
|
|
||||||
chartbuilder = ChartBuilder(main_chart)
|
chartbuilder = ChartBuilder(main_chart)
|
||||||
helm_chart = chartbuilder.get_helm_chart()
|
helm_chart = chartbuilder.get_helm_chart()
|
||||||
|
@ -409,8 +420,8 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self.addCleanup(shutil.rmtree, chart_dir.path)
|
self.addCleanup(shutil.rmtree, chart_dir.path)
|
||||||
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
self._write_temporary_file_contents(chart_dir.path, 'Chart.yaml',
|
||||||
self.chart_yaml)
|
self.chart_yaml)
|
||||||
ch = yaml.safe_load(self.chart_stream)['chart']
|
ch = yaml.safe_load(self.chart_stream)
|
||||||
ch['source_dir'] = (chart_dir.path, '')
|
ch['data']['source_dir'] = (chart_dir.path, '')
|
||||||
|
|
||||||
test_chart = ch
|
test_chart = ch
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
chartbuilder = ChartBuilder(test_chart)
|
||||||
|
@ -424,10 +435,10 @@ class ChartBuilderTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(dep_chart_dir.path, 'Chart.yaml',
|
self._write_temporary_file_contents(dep_chart_dir.path, 'Chart.yaml',
|
||||||
self.dependency_chart_yaml)
|
self.dependency_chart_yaml)
|
||||||
dep_ch = yaml.safe_load(self.dependency_chart_stream)
|
dep_ch = yaml.safe_load(self.dependency_chart_stream)
|
||||||
dep_ch['chart']['source_dir'] = (dep_chart_dir.path, '')
|
dep_ch['data']['source_dir'] = (dep_chart_dir.path, '')
|
||||||
|
|
||||||
dependency_chart = dep_ch
|
dependency_chart = dep_ch
|
||||||
test_chart['dependencies'] = [dependency_chart]
|
test_chart['data']['dependencies'] = [dependency_chart]
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
chartbuilder = ChartBuilder(test_chart)
|
||||||
|
|
||||||
re = inspect.cleandoc("""
|
re = inspect.cleandoc("""
|
||||||
|
@ -457,8 +468,7 @@ class ChartBuilderNegativeTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(
|
self._write_temporary_file_contents(
|
||||||
chart_dir.path, filename, "DIRC^@^@^@^B^@^@^@×Z®<86>F.1")
|
chart_dir.path, filename, "DIRC^@^@^@^B^@^@^@×Z®<86>F.1")
|
||||||
|
|
||||||
test_chart = {'source_dir': (chart_dir.path, '')}
|
chartbuilder = ChartBuilder(self._get_test_chart(chart_dir))
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
|
||||||
|
|
||||||
# Confirm it failed for both encodings.
|
# Confirm it failed for both encodings.
|
||||||
error_re = (r'.*A str exception occurred while trying to read file:'
|
error_re = (r'.*A str exception occurred while trying to read file:'
|
||||||
|
@ -477,8 +487,7 @@ class ChartBuilderNegativeTestCase(BaseChartBuilderTestCase):
|
||||||
self._write_temporary_file_contents(
|
self._write_temporary_file_contents(
|
||||||
chart_dir.path, filename, "DIRC^@^@^@^B^@^@^@×Z®<86>F.1")
|
chart_dir.path, filename, "DIRC^@^@^@^B^@^@^@×Z®<86>F.1")
|
||||||
|
|
||||||
test_chart = {'source_dir': (chart_dir.path, '')}
|
chartbuilder = ChartBuilder(self._get_test_chart(chart_dir))
|
||||||
chartbuilder = ChartBuilder(test_chart)
|
|
||||||
|
|
||||||
side_effects = [self.exc_to_raise, "", ""]
|
side_effects = [self.exc_to_raise, "", ""]
|
||||||
with mock.patch("builtins.open", mock.mock_open(read_data="")) \
|
with mock.patch("builtins.open", mock.mock_open(read_data="")) \
|
||||||
|
|
|
@ -18,9 +18,9 @@ import yaml
|
||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from armada import const
|
|
||||||
from armada import exceptions
|
from armada import exceptions
|
||||||
from armada.handlers import manifest
|
from armada.handlers import manifest
|
||||||
|
from armada.handlers import schema
|
||||||
from armada.utils import validate
|
from armada.utils import validate
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ class ManifestTestCase(testtools.TestCase):
|
||||||
self.documents, target_manifest='armada-manifest')
|
self.documents, target_manifest='armada-manifest')
|
||||||
obtained_manifest = armada_manifest.get_manifest()
|
obtained_manifest = armada_manifest.get_manifest()
|
||||||
self.assertIsInstance(obtained_manifest, dict)
|
self.assertIsInstance(obtained_manifest, dict)
|
||||||
self.assertEqual(obtained_manifest['armada'],
|
self.assertEqual(obtained_manifest['data'],
|
||||||
armada_manifest.manifest['data'])
|
armada_manifest.manifest['data'])
|
||||||
|
|
||||||
def test_find_documents(self):
|
def test_find_documents(self):
|
||||||
|
@ -194,19 +194,15 @@ class ManifestTestCase(testtools.TestCase):
|
||||||
# the first chart group in the Armada manifest
|
# the first chart group in the Armada manifest
|
||||||
keystone_infra_services_chart_group = armada_manifest. \
|
keystone_infra_services_chart_group = armada_manifest. \
|
||||||
find_chart_group_document('keystone-infra-services')
|
find_chart_group_document('keystone-infra-services')
|
||||||
keystone_infra_services_chart_group_data = \
|
|
||||||
keystone_infra_services_chart_group.get('data')
|
|
||||||
|
|
||||||
self.assertEqual(keystone_infra_services_chart_group_data,
|
self.assertEqual(keystone_infra_services_chart_group,
|
||||||
built_armada_manifest['data']['chart_groups'][0])
|
built_armada_manifest['data']['chart_groups'][0])
|
||||||
|
|
||||||
# the first chart group in the Armada manifest
|
# the first chart group in the Armada manifest
|
||||||
openstack_keystone_chart_group = armada_manifest. \
|
openstack_keystone_chart_group = armada_manifest. \
|
||||||
find_chart_group_document('openstack-keystone')
|
find_chart_group_document('openstack-keystone')
|
||||||
openstack_keystone_chart_group_data = \
|
|
||||||
openstack_keystone_chart_group.get('data')
|
|
||||||
|
|
||||||
self.assertEqual(openstack_keystone_chart_group_data,
|
self.assertEqual(openstack_keystone_chart_group,
|
||||||
built_armada_manifest['data']['chart_groups'][1])
|
built_armada_manifest['data']['chart_groups'][1])
|
||||||
|
|
||||||
def test_verify_build_chart_group_deps(self):
|
def test_verify_build_chart_group_deps(self):
|
||||||
|
@ -218,7 +214,7 @@ class ManifestTestCase(testtools.TestCase):
|
||||||
build_chart_group(chart_group)
|
build_chart_group(chart_group)
|
||||||
openstack_keystone_chart_group_deps_dep_added = \
|
openstack_keystone_chart_group_deps_dep_added = \
|
||||||
openstack_keystone_chart_group_deps[
|
openstack_keystone_chart_group_deps[
|
||||||
'data']['chart_group'][0]['chart']['dependencies']
|
'data']['chart_group'][0]['data']['dependencies']
|
||||||
|
|
||||||
# keystone chart dependencies
|
# keystone chart dependencies
|
||||||
keystone_chart = armada_manifest.find_chart_document('keystone')
|
keystone_chart = armada_manifest.find_chart_document('keystone')
|
||||||
|
@ -237,7 +233,7 @@ class ManifestTestCase(testtools.TestCase):
|
||||||
build_chart_group(chart_group)
|
build_chart_group(chart_group)
|
||||||
keystone_infra_services_dep_added = \
|
keystone_infra_services_dep_added = \
|
||||||
openstack_keystone_chart_group_deps[
|
openstack_keystone_chart_group_deps[
|
||||||
'data']['chart_group'][0]['chart']['dependencies']
|
'data']['chart_group'][0]['data']['dependencies']
|
||||||
|
|
||||||
# building mariadb chart dependencies
|
# building mariadb chart dependencies
|
||||||
mariadb_chart = armada_manifest.find_chart_document('mariadb')
|
mariadb_chart = armada_manifest.find_chart_document('mariadb')
|
||||||
|
@ -274,9 +270,7 @@ class ManifestTestCase(testtools.TestCase):
|
||||||
|
|
||||||
# helm-toolkit dependency, the basis for comparison of d
|
# helm-toolkit dependency, the basis for comparison of d
|
||||||
# ependencies in other charts
|
# ependencies in other charts
|
||||||
expected_helm_toolkit_dependency = {
|
expected_helm_toolkit_dependency = helm_toolkit_chart
|
||||||
'chart': helm_toolkit_chart.get('data')
|
|
||||||
}
|
|
||||||
|
|
||||||
# keystone chart dependencies
|
# keystone chart dependencies
|
||||||
keystone_chart = armada_manifest.find_chart_document('keystone')
|
keystone_chart = armada_manifest.find_chart_document('keystone')
|
||||||
|
@ -366,42 +360,39 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
||||||
documents,
|
documents,
|
||||||
target_manifest='armada-manifest')
|
target_manifest='armada-manifest')
|
||||||
|
|
||||||
|
def _assert_missing_documents_raises(self, documents):
|
||||||
|
error_re = ('.*Documents must include at least one of each of .* and '
|
||||||
|
'only one .*')
|
||||||
|
self.assertRaisesRegexp(exceptions.ManifestException, error_re,
|
||||||
|
manifest.Manifest, documents)
|
||||||
|
|
||||||
def test_get_documents_missing_manifest(self):
|
def test_get_documents_missing_manifest(self):
|
||||||
# Validates exceptions.ManifestException is thrown if no manifest is
|
# Validates exceptions.ManifestException is thrown if no manifest is
|
||||||
# found. Manifest is last document in sample YAML.
|
# found. Manifest is last document in sample YAML.
|
||||||
error_re = ('Documents must be a list of documents with at least one '
|
self._assert_missing_documents_raises(self.documents[:-1])
|
||||||
'of each of the following schemas: .*')
|
|
||||||
self.assertRaisesRegexp(exceptions.ManifestException, error_re,
|
|
||||||
manifest.Manifest, self.documents[:-1])
|
|
||||||
|
|
||||||
def test_get_documents_missing_charts(self):
|
def test_get_documents_missing_charts(self):
|
||||||
# Validates exceptions.ManifestException is thrown if no chart is
|
# Validates exceptions.ManifestException is thrown if no chart is
|
||||||
# found. Charts are first 5 documents in sample YAML.
|
# found. Charts are first 5 documents in sample YAML.
|
||||||
error_re = ('Documents must be a list of documents with at least one '
|
self._assert_missing_documents_raises(self.documents[5:])
|
||||||
'of each of the following schemas: .*')
|
|
||||||
self.assertRaisesRegexp(exceptions.ManifestException, error_re,
|
|
||||||
manifest.Manifest, self.documents[5:])
|
|
||||||
|
|
||||||
def test_get_documents_missing_chart_groups(self):
|
def test_get_documents_missing_chart_groups(self):
|
||||||
# Validates exceptions.ManifestException is thrown if no chart is
|
# Validates exceptions.ManifestException is thrown if no chart is
|
||||||
# found. ChartGroups are 5-6 documents in sample YAML.
|
# found. ChartGroups are 5-6 documents in sample YAML.
|
||||||
documents = self.documents[:4] + [self.documents[-1]]
|
documents = self.documents[:4] + [self.documents[-1]]
|
||||||
error_re = ('Documents must be a list of documents with at least one '
|
self._assert_missing_documents_raises(documents)
|
||||||
'of each of the following schemas: .*')
|
|
||||||
self.assertRaisesRegexp(exceptions.ManifestException, error_re,
|
|
||||||
manifest.Manifest, documents)
|
|
||||||
|
|
||||||
def test_find_chart_document_negative(self):
|
def test_find_chart_document_negative(self):
|
||||||
armada_manifest = manifest.Manifest(self.documents)
|
armada_manifest = manifest.Manifest(self.documents)
|
||||||
error_re = r'Could not build %s named "%s"' % (const.DOCUMENT_CHART,
|
error_re = r'.*Could not find %s named "%s"' % (schema.TYPE_CHART,
|
||||||
'invalid')
|
'invalid')
|
||||||
self.assertRaisesRegexp(exceptions.BuildChartException, error_re,
|
self.assertRaisesRegexp(exceptions.BuildChartException, error_re,
|
||||||
armada_manifest.find_chart_document, 'invalid')
|
armada_manifest.find_chart_document, 'invalid')
|
||||||
|
|
||||||
def test_find_group_document_negative(self):
|
def test_find_group_document_negative(self):
|
||||||
armada_manifest = manifest.Manifest(self.documents)
|
armada_manifest = manifest.Manifest(self.documents)
|
||||||
error_re = r'Could not build %s named "%s"' % (const.DOCUMENT_GROUP,
|
error_re = r'.*Could not find %s named "%s"' % (schema.TYPE_CHARTGROUP,
|
||||||
'invalid')
|
'invalid')
|
||||||
self.assertRaisesRegexp(exceptions.BuildChartGroupException, error_re,
|
self.assertRaisesRegexp(exceptions.BuildChartGroupException, error_re,
|
||||||
armada_manifest.find_chart_group_document,
|
armada_manifest.find_chart_group_document,
|
||||||
'invalid')
|
'invalid')
|
||||||
|
|
|
@ -20,8 +20,8 @@ import yaml
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from armada.handlers.override import Override
|
from armada.handlers.override import Override
|
||||||
|
from armada.handlers import schema
|
||||||
from armada.exceptions import override_exceptions
|
from armada.exceptions import override_exceptions
|
||||||
from armada import const
|
|
||||||
|
|
||||||
|
|
||||||
class OverrideTestCase(testtools.TestCase):
|
class OverrideTestCase(testtools.TestCase):
|
||||||
|
@ -117,13 +117,13 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
documents = list(yaml.safe_load_all(f.read()))
|
documents = list(yaml.safe_load_all(f.read()))
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
test_group = ovr.find_document_type('chart_group')
|
test_group = ovr.find_document_type('chart_group')
|
||||||
self.assertEqual(test_group, const.DOCUMENT_GROUP)
|
self.assertEqual(test_group, schema.TYPE_CHARTGROUP)
|
||||||
|
|
||||||
test_chart = ovr.find_document_type('chart')
|
test_chart = ovr.find_document_type('chart')
|
||||||
self.assertEqual(test_chart, const.DOCUMENT_CHART)
|
self.assertEqual(test_chart, schema.TYPE_CHART)
|
||||||
|
|
||||||
test_manifest = ovr.find_document_type('manifest')
|
test_manifest = ovr.find_document_type('manifest')
|
||||||
self.assertEqual(test_manifest, const.DOCUMENT_MANIFEST)
|
self.assertEqual(test_manifest, schema.TYPE_MANIFEST)
|
||||||
|
|
||||||
def test_update_chart_document_valid(self):
|
def test_update_chart_document_valid(self):
|
||||||
with open(self.base_manifest) as f:
|
with open(self.base_manifest) as f:
|
||||||
|
@ -138,7 +138,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
|
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
# update with document values with the modified ones
|
# update with document values with the modified ones
|
||||||
ovr.update_chart_document(documents_modified[0])
|
ovr.update_document(documents_modified[0])
|
||||||
|
|
||||||
# after the update, both documents are equal
|
# after the update, both documents are equal
|
||||||
self.assertEqual(ovr.documents[0]['data']['chart_name'],
|
self.assertEqual(ovr.documents[0]['data']['chart_name'],
|
||||||
|
@ -148,7 +148,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
# Case 2: Checking if dictionaries get updated
|
# Case 2: Checking if dictionaries get updated
|
||||||
documents_modified[0]['data']['values'] = {'foo': 'bar'}
|
documents_modified[0]['data']['values'] = {'foo': 'bar'}
|
||||||
|
|
||||||
ovr.update_chart_document(documents_modified[0])
|
ovr.update_document(documents_modified[0])
|
||||||
|
|
||||||
# after the update, both documents are equal
|
# after the update, both documents are equal
|
||||||
self.assertEqual(ovr.documents[0]['data']['values'],
|
self.assertEqual(ovr.documents[0]['data']['values'],
|
||||||
|
@ -158,7 +158,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
# Case 3: Checking if lists get updated
|
# Case 3: Checking if lists get updated
|
||||||
documents_modified[0]['data']['dependencies'] = ['foo', 'bar']
|
documents_modified[0]['data']['dependencies'] = ['foo', 'bar']
|
||||||
|
|
||||||
ovr.update_chart_document(documents_modified[0])
|
ovr.update_document(documents_modified[0])
|
||||||
|
|
||||||
# after the update, both documents are equal
|
# after the update, both documents are equal
|
||||||
self.assertEqual(['foo', 'bar'],
|
self.assertEqual(['foo', 'bar'],
|
||||||
|
@ -179,7 +179,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
|
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
# update with document values with the modified ones
|
# update with document values with the modified ones
|
||||||
ovr.update_chart_document(documents_modified[0])
|
ovr.update_document(documents_modified[0])
|
||||||
|
|
||||||
self.assertIn('chart_name', ovr.documents[0]['data'])
|
self.assertIn('chart_name', ovr.documents[0]['data'])
|
||||||
self.assertNotEqual(ovr.documents[0], documents_modified[0])
|
self.assertNotEqual(ovr.documents[0], documents_modified[0])
|
||||||
|
@ -195,7 +195,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
|
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
# update with document values with the modified ones
|
# update with document values with the modified ones
|
||||||
ovr.update_chart_group_document(documents_modified[1])
|
ovr.update_document(documents_modified[1])
|
||||||
|
|
||||||
# after the update, both documents are equal
|
# after the update, both documents are equal
|
||||||
self.assertEqual(ovr.documents[1]['data']['sequenced'],
|
self.assertEqual(ovr.documents[1]['data']['sequenced'],
|
||||||
|
@ -214,7 +214,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
|
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
# update with document values with the modified ones
|
# update with document values with the modified ones
|
||||||
ovr.update_chart_group_document(documents_modified[1])
|
ovr.update_document(documents_modified[1])
|
||||||
|
|
||||||
self.assertIn('sequenced', ovr.documents[1]['data'])
|
self.assertIn('sequenced', ovr.documents[1]['data'])
|
||||||
self.assertNotEqual(ovr.documents[1], documents_modified[1])
|
self.assertNotEqual(ovr.documents[1], documents_modified[1])
|
||||||
|
@ -230,7 +230,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
|
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
# update with document values with the modified ones
|
# update with document values with the modified ones
|
||||||
ovr.update_armada_manifest(documents_modified[2])
|
ovr.update_document(documents_modified[2])
|
||||||
|
|
||||||
# after the update, both documents are equal
|
# after the update, both documents are equal
|
||||||
self.assertEqual(ovr.documents[2]['data']['release_prefix'],
|
self.assertEqual(ovr.documents[2]['data']['release_prefix'],
|
||||||
|
@ -249,7 +249,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
|
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
# update with document values from base_manifest
|
# update with document values from base_manifest
|
||||||
ovr.update_armada_manifest(documents_modified[2])
|
ovr.update_document(documents_modified[2])
|
||||||
|
|
||||||
self.assertIn('release_prefix', ovr.documents[2]['data'])
|
self.assertIn('release_prefix', ovr.documents[2]['data'])
|
||||||
self.assertNotEqual(ovr.documents[2], documents_modified[2])
|
self.assertNotEqual(ovr.documents[2], documents_modified[2])
|
||||||
|
@ -265,7 +265,7 @@ class OverrideTestCase(testtools.TestCase):
|
||||||
documents = list(yaml.safe_load_all(f.read()))
|
documents = list(yaml.safe_load_all(f.read()))
|
||||||
doc_path = ['chart', 'blog-1']
|
doc_path = ['chart', 'blog-1']
|
||||||
ovr = Override(documents)
|
ovr = Override(documents)
|
||||||
ovr.update_document(merging_values)
|
ovr.update_documents(merging_values)
|
||||||
ovr_doc = ovr.find_manifest_document(doc_path)
|
ovr_doc = ovr.find_manifest_document(doc_path)
|
||||||
expect_doc = list(yaml.load_all(e.read()))[0]
|
expect_doc = list(yaml.load_all(e.read()))[0]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Copyright 2019 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 unittest
|
||||||
|
|
||||||
|
from armada.utils import schema
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_validate_load_schemas(self):
|
||||||
|
expected_schemas = [
|
||||||
|
'armada/Chart/v1', 'armada/ChartGroup/v1', 'armada/Manifest/v1'
|
||||||
|
'armada/Chart/v2', 'armada/ChartGroup/v2', 'armada/Manifest/v2'
|
||||||
|
]
|
||||||
|
for expected_schema in expected_schemas:
|
||||||
|
self.assertIn(expected_schema, schema._SCHEMAS)
|
||||||
|
|
||||||
|
def test_validate_load_duplicate_schemas_expect_runtime_error(self):
|
||||||
|
"""Validate that calling ``_load_schemas`` results in a
|
||||||
|
``RuntimeError`` being thrown, because the call is made during module
|
||||||
|
import, and importing the schemas again in manually results in
|
||||||
|
duplicates.
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegexp(RuntimeError,
|
||||||
|
'Duplicate schema specified for: .*'):
|
||||||
|
schema._load_schemas()
|
|
@ -111,13 +111,6 @@ class ValidateOwnExamplesTestCase(BaseValidateTest):
|
||||||
|
|
||||||
class ValidateTestCase(BaseValidateTest):
|
class ValidateTestCase(BaseValidateTest):
|
||||||
|
|
||||||
def test_validate_load_schemas(self):
|
|
||||||
expected_schemas = [
|
|
||||||
'armada/Chart/v1', 'armada/ChartGroup/v1', 'armada/Manifest/v1'
|
|
||||||
]
|
|
||||||
for expected_schema in expected_schemas:
|
|
||||||
self.assertIn(expected_schema, validate.SCHEMAS)
|
|
||||||
|
|
||||||
def test_validate_armada_yaml_passes(self):
|
def test_validate_armada_yaml_passes(self):
|
||||||
template = '{}/resources/valid_armada_document.yaml'.format(
|
template = '{}/resources/valid_armada_document.yaml'.format(
|
||||||
self.basepath)
|
self.basepath)
|
||||||
|
@ -223,16 +216,6 @@ data:
|
||||||
|
|
||||||
class ValidateNegativeTestCase(BaseValidateTest):
|
class ValidateNegativeTestCase(BaseValidateTest):
|
||||||
|
|
||||||
def test_validate_load_duplicate_schemas_expect_runtime_error(self):
|
|
||||||
"""Validate that calling ``validate._load_schemas`` results in a
|
|
||||||
``RuntimeError`` being thrown, because the call is made during module
|
|
||||||
import, and importing the schemas again in manually results in
|
|
||||||
duplicates.
|
|
||||||
"""
|
|
||||||
with self.assertRaisesRegexp(RuntimeError,
|
|
||||||
'Duplicate schema specified for: .*'):
|
|
||||||
validate._load_schemas()
|
|
||||||
|
|
||||||
def test_validate_no_dictionary_expect_type_error(self):
|
def test_validate_no_dictionary_expect_type_error(self):
|
||||||
expected_error = 'The provided input "invalid" must be a dictionary.'
|
expected_error = 'The provided input "invalid" must be a dictionary.'
|
||||||
self.assertRaisesRegexp(TypeError, expected_error,
|
self.assertRaisesRegexp(TypeError, expected_error,
|
||||||
|
|
|
@ -13,44 +13,18 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import jsonschema
|
import jsonschema
|
||||||
import os
|
|
||||||
import pkg_resources
|
|
||||||
import requests
|
import requests
|
||||||
import traceback
|
import traceback
|
||||||
import yaml
|
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from armada.const import KEYWORD_GROUPS, KEYWORD_CHARTS, KEYWORD_RELEASE
|
from armada import const
|
||||||
|
from armada.handlers import schema as sch
|
||||||
from armada.handlers.manifest import Manifest
|
from armada.handlers.manifest import Manifest
|
||||||
from armada.exceptions.manifest_exceptions import ManifestException
|
from armada.exceptions.manifest_exceptions import ManifestException
|
||||||
from armada.utils.validation_message import ValidationMessage
|
from armada.utils.validation_message import ValidationMessage
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
# Creates a mapping between ``metadata.name``: ``data`` where the
|
|
||||||
# ``metadata.name`` is the ``schema`` of a manifest and the ``data`` is the
|
|
||||||
# JSON schema to be used to validate the manifest in question.
|
|
||||||
SCHEMAS = {}
|
|
||||||
|
|
||||||
|
|
||||||
def _get_schema_dir():
|
|
||||||
return pkg_resources.resource_filename('armada', 'schemas')
|
|
||||||
|
|
||||||
|
|
||||||
def _load_schemas():
|
|
||||||
"""Populates ``SCHEMAS`` with the schemas defined in package
|
|
||||||
``armada.schemas``.
|
|
||||||
|
|
||||||
"""
|
|
||||||
schema_dir = _get_schema_dir()
|
|
||||||
for schema_file in os.listdir(schema_dir):
|
|
||||||
with open(os.path.join(schema_dir, schema_file)) as f:
|
|
||||||
for schema in yaml.safe_load_all(f):
|
|
||||||
name = schema['metadata']['name']
|
|
||||||
if name in SCHEMAS:
|
|
||||||
raise RuntimeError(
|
|
||||||
'Duplicate schema specified for: %s.' % name)
|
|
||||||
SCHEMAS[name] = schema['data']
|
|
||||||
|
|
||||||
|
|
||||||
def _validate_armada_manifest(manifest):
|
def _validate_armada_manifest(manifest):
|
||||||
|
@ -71,7 +45,7 @@ def _validate_armada_manifest(manifest):
|
||||||
details = []
|
details = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
armada_object = manifest.get_manifest().get('armada')
|
manifest.get_manifest().get(const.KEYWORD_DATA)
|
||||||
except ManifestException as me:
|
except ManifestException as me:
|
||||||
vmsg = ValidationMessage(
|
vmsg = ValidationMessage(
|
||||||
message=str(me), error=True, name='ARM001', level='Error')
|
message=str(me), error=True, name='ARM001', level='Error')
|
||||||
|
@ -80,27 +54,6 @@ def _validate_armada_manifest(manifest):
|
||||||
details.append(vmsg.get_output())
|
details.append(vmsg.get_output())
|
||||||
return False, details
|
return False, details
|
||||||
|
|
||||||
groups = armada_object.get(KEYWORD_GROUPS)
|
|
||||||
|
|
||||||
if not isinstance(groups, list):
|
|
||||||
message = '{} entry is of wrong type: {} (expected: {})'.format(
|
|
||||||
KEYWORD_GROUPS, type(groups), 'list')
|
|
||||||
vmsg = ValidationMessage(
|
|
||||||
message=message, error=True, name='ARM101', level='Error')
|
|
||||||
LOG.info('ValidationMessage: %s', vmsg.get_output_json())
|
|
||||||
details.append(vmsg.get_output())
|
|
||||||
|
|
||||||
for group in groups:
|
|
||||||
for chart in group.get(KEYWORD_CHARTS):
|
|
||||||
chart_obj = chart.get('chart')
|
|
||||||
if KEYWORD_RELEASE not in chart_obj:
|
|
||||||
message = 'Could not find {} keyword in {}'.format(
|
|
||||||
KEYWORD_RELEASE, chart_obj.get('release'))
|
|
||||||
vmsg = ValidationMessage(
|
|
||||||
message=message, error=True, name='ARM102', level='Error')
|
|
||||||
LOG.info('ValidationMessage: %s', vmsg.get_output_json())
|
|
||||||
details.append(vmsg.get_output())
|
|
||||||
|
|
||||||
if len([x for x in details if x.get('error', False)]) > 0:
|
if len([x for x in details if x.get('error', False)]) > 0:
|
||||||
return False, details
|
return False, details
|
||||||
|
|
||||||
|
@ -117,13 +70,16 @@ def validate_armada_manifests(documents):
|
||||||
all_valid = True
|
all_valid = True
|
||||||
|
|
||||||
for document in documents:
|
for document in documents:
|
||||||
if document.get('schema', '') == 'armada/Manifest/v1':
|
doc_schema = document.get('schema')
|
||||||
target = document.get('metadata').get('name')
|
if doc_schema:
|
||||||
# TODO(MarshM) explore: why does this pass 'documents'?
|
schema_info = sch.get_schema_info(doc_schema)
|
||||||
manifest = Manifest(documents, target_manifest=target)
|
if schema_info and schema_info.type == sch.TYPE_MANIFEST:
|
||||||
is_valid, details = _validate_armada_manifest(manifest)
|
target = document.get('metadata').get('name')
|
||||||
all_valid = all_valid and is_valid
|
# TODO(MarshM) explore: why does this pass 'documents'?
|
||||||
messages.extend(details)
|
manifest = Manifest(documents, target_manifest=target)
|
||||||
|
is_valid, details = _validate_armada_manifest(manifest)
|
||||||
|
all_valid = all_valid and is_valid
|
||||||
|
messages.extend(details)
|
||||||
|
|
||||||
return all_valid, messages
|
return all_valid, messages
|
||||||
|
|
||||||
|
@ -151,9 +107,10 @@ def validate_armada_document(document):
|
||||||
details = []
|
details = []
|
||||||
LOG.debug('Validating document [%s] %s', schema, document_name)
|
LOG.debug('Validating document [%s] %s', schema, document_name)
|
||||||
|
|
||||||
if schema in SCHEMAS:
|
schema_info = sch.get_schema_info(schema)
|
||||||
|
if schema_info:
|
||||||
try:
|
try:
|
||||||
validator = jsonschema.Draft4Validator(SCHEMAS[schema])
|
validator = jsonschema.Draft4Validator(schema_info.data)
|
||||||
for error in validator.iter_errors(document.get('data')):
|
for error in validator.iter_errors(document.get('data')):
|
||||||
error_message = "Invalid document [%s] %s: %s." % \
|
error_message = "Invalid document [%s] %s: %s." % \
|
||||||
(schema, document_name, error.message)
|
(schema, document_name, error.message)
|
||||||
|
@ -222,7 +179,3 @@ def validate_manifest_url(value):
|
||||||
return (requests.get(value).status_code == 200)
|
return (requests.get(value).status_code == 200)
|
||||||
except requests.exceptions.RequestException:
|
except requests.exceptions.RequestException:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# Fill the cache.
|
|
||||||
_load_schemas()
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
..
|
||||||
|
Copyright 2019 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Document Authoring Guide
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Contents:
|
||||||
|
|
||||||
|
v1/index
|
||||||
|
v2/index
|
||||||
|
migration-v1-v2
|
|
@ -0,0 +1,70 @@
|
||||||
|
..
|
||||||
|
Copyright 2019 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
v1-v2 Migration
|
||||||
|
===============
|
||||||
|
|
||||||
|
The following migrations must be done when moving from :ref:`v1 <document_authoring_v1>` to :ref:`v2 <document_authoring_v2>` docs.
|
||||||
|
|
||||||
|
Chart
|
||||||
|
-----
|
||||||
|
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| change | migration |
|
||||||
|
+================================+============================================================+
|
||||||
|
| ``chart_name`` removed | Remove. It was redundant with ``metadata.name`` while at |
|
||||||
|
| | the same time not guaranteeing uniqueness. Log messages now|
|
||||||
|
| | reference ``metadata.name`` for improved grep-ability. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``test`` as a boolean removed | :ref:`test <test_v2>` must now be an object. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``timeout`` removed | Use ``wait.timeout`` instead. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``install`` removed | Remove. Previously unused. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``upgrade.post`` removed | Remove. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``upgrade.pre.update`` removed | Remove. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``upgrade.pre.create`` removed | Remove. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``upgrade.pre.delete[*].name`` | Remove. |
|
||||||
|
| removed | |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``upgrade.pre.delete[*]`` | If you have an item in ``upgrade.pre.delete`` and |
|
||||||
|
| with ``type: job`` no longer | ``type: job`` and you also want to delete cronjobs, add |
|
||||||
|
| deletes cronjobs | another item with ``type: cronjob`` and same labels. |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
| ``dependencies``, | Remove as desired. |
|
||||||
|
| ``upgrade.no_hooks``, | |
|
||||||
|
| ``source.subpath`` | |
|
||||||
|
| now optional | |
|
||||||
|
+--------------------------------+------------------------------------------------------------+
|
||||||
|
|
||||||
|
ChartGroup
|
||||||
|
----------
|
||||||
|
|
||||||
|
+--------------------------+-----------------------------------------------------------+
|
||||||
|
| change | migration |
|
||||||
|
+==========================+===========================================================+
|
||||||
|
| ``test_charts`` removed | Use the Chart schema's :ref:`test.enabled <test_v2>` |
|
||||||
|
| | instead. |
|
||||||
|
+--------------------------+-----------------------------------------------------------+
|
||||||
|
|
||||||
|
Manifest
|
||||||
|
--------
|
||||||
|
|
||||||
|
No changes.
|
|
@ -1,5 +1,23 @@
|
||||||
Armada - Making Your First Armada Manifest
|
..
|
||||||
==========================================
|
Copyright 2019 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
.. _document_authoring_v1:
|
||||||
|
|
||||||
|
v1 Authoring
|
||||||
|
============
|
||||||
|
|
||||||
armada/Manifest/v1
|
armada/Manifest/v1
|
||||||
------------------
|
------------------
|
||||||
|
@ -191,9 +209,6 @@ Run helm tests on the chart after install/upgrade.
|
||||||
deprecated and will be removed. The ``cleanup`` option below is set to true
|
deprecated and will be removed. The ``cleanup`` option below is set to true
|
||||||
in this case for backward compatibility.
|
in this case for backward compatibility.
|
||||||
|
|
||||||
.. _test_options:
|
|
||||||
|
|
||||||
|
|
||||||
Test Options
|
Test Options
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
..
|
||||||
|
Copyright 2019 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
v1
|
||||||
|
==
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Contents:
|
||||||
|
|
||||||
|
document-authoring
|
||||||
|
schemas
|
|
@ -14,15 +14,11 @@
|
||||||
License for the specific language governing permissions and limitations
|
License for the specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
|
|
||||||
.. _armada-documents:
|
v1 Schemas
|
||||||
|
==========
|
||||||
|
|
||||||
Armada Documents
|
Below are the schemas Armada uses to validate Charts, Chart Groups, and
|
||||||
================
|
Manifests.
|
||||||
|
|
||||||
Below are the schemas Armada uses to validate :ref:`Charts`,
|
|
||||||
:ref:`Chart Groups`, and :ref:`Manifests`.
|
|
||||||
|
|
||||||
.. _Charts:
|
|
||||||
|
|
||||||
Charts
|
Charts
|
||||||
------
|
------
|
||||||
|
@ -32,16 +28,12 @@ comparable to a Helm chart. Charts consist of all the labels, dependencies,
|
||||||
install and upgrade information, hooks and additional information needed to
|
install and upgrade information, hooks and additional information needed to
|
||||||
convey to Tiller.
|
convey to Tiller.
|
||||||
|
|
||||||
.. _Chart Groups:
|
|
||||||
|
|
||||||
Chart Groups
|
Chart Groups
|
||||||
------------
|
------------
|
||||||
|
|
||||||
A ``Chart Group`` consists of a list of charts. ``Chart Group`` documents are
|
A ``Chart Group`` consists of a list of charts. ``Chart Group`` documents are
|
||||||
useful for managing a group of ``Chart`` documents together.
|
useful for managing a group of ``Chart`` documents together.
|
||||||
|
|
||||||
.. _Manifests:
|
|
||||||
|
|
||||||
Manifests
|
Manifests
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -76,7 +68,7 @@ Schemas
|
||||||
``metadata.name`` are validated.
|
``metadata.name`` are validated.
|
||||||
|
|
||||||
.. literalinclude::
|
.. literalinclude::
|
||||||
../../../armada/schemas/armada-chart-schema.yaml
|
../../../../../armada/schemas/armada-chart-schema-v1.yaml
|
||||||
:language: yaml
|
:language: yaml
|
||||||
:lines: 15-
|
:lines: 15-
|
||||||
:caption: Schema for ``armada/Chart/v1`` documents.
|
:caption: Schema for ``armada/Chart/v1`` documents.
|
||||||
|
@ -90,7 +82,7 @@ Schemas
|
||||||
``metadata.name`` are validated.
|
``metadata.name`` are validated.
|
||||||
|
|
||||||
.. literalinclude::
|
.. literalinclude::
|
||||||
../../../armada/schemas/armada-chartgroup-schema.yaml
|
../../../../../armada/schemas/armada-chartgroup-schema-v1.yaml
|
||||||
:language: yaml
|
:language: yaml
|
||||||
:lines: 15-
|
:lines: 15-
|
||||||
:caption: Schema for ``armada/ChartGroup/v1`` documents.
|
:caption: Schema for ``armada/ChartGroup/v1`` documents.
|
||||||
|
@ -104,7 +96,7 @@ Schemas
|
||||||
``metadata.name`` are validated.
|
``metadata.name`` are validated.
|
||||||
|
|
||||||
.. literalinclude::
|
.. literalinclude::
|
||||||
../../../armada/schemas/armada-manifest-schema.yaml
|
../../../../../armada/schemas/armada-manifest-schema-v1.yaml
|
||||||
:language: yaml
|
:language: yaml
|
||||||
:lines: 15-
|
:lines: 15-
|
||||||
:caption: Schema for ``armada/Manifest/v1`` documents.
|
:caption: Schema for ``armada/Manifest/v1`` documents.
|
||||||
|
@ -112,8 +104,6 @@ Schemas
|
||||||
This schema is used to sanity-check all ``Manifest`` documents that are passed
|
This schema is used to sanity-check all ``Manifest`` documents that are passed
|
||||||
to Armada.
|
to Armada.
|
||||||
|
|
||||||
.. _authoring-guidelines:
|
|
||||||
|
|
||||||
Authoring Guidelines
|
Authoring Guidelines
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
@ -0,0 +1,469 @@
|
||||||
|
..
|
||||||
|
Copyright 2019 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
.. _document_authoring_v2:
|
||||||
|
|
||||||
|
v2 Authoring
|
||||||
|
============
|
||||||
|
|
||||||
|
.. DANGER::
|
||||||
|
|
||||||
|
EXPERIMENTAL: `v2` docs are still experimental and WILL have breaking changes
|
||||||
|
before they are finalized.
|
||||||
|
|
||||||
|
armada/Manifest/v2
|
||||||
|
------------------
|
||||||
|
|
||||||
|
+---------------------+--------+-------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=====================+========+=========================+
|
||||||
|
| ``release_prefix`` | string | appends to the |
|
||||||
|
| | | front of all |
|
||||||
|
| | | charts |
|
||||||
|
| | | released |
|
||||||
|
| | | by the |
|
||||||
|
| | | manifest in |
|
||||||
|
| | | order to |
|
||||||
|
| | | manage releases |
|
||||||
|
| | | throughout their |
|
||||||
|
| | | lifecycle |
|
||||||
|
+---------------------+--------+-------------------------+
|
||||||
|
| ``chart_groups`` | array | A list of the |
|
||||||
|
| | | ``metadata.name`` of |
|
||||||
|
| | | each ``ChartGroup`` to |
|
||||||
|
| | | deploy in order. |
|
||||||
|
+---------------------+--------+-------------------------+
|
||||||
|
|
||||||
|
Manifest Example
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
---
|
||||||
|
schema: armada/Manifest/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: simple-armada
|
||||||
|
data:
|
||||||
|
release_prefix: armada
|
||||||
|
chart_groups:
|
||||||
|
- chart_group
|
||||||
|
|
||||||
|
|
||||||
|
armada/ChartGroup/v2
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
+-----------------+----------+------------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=================+==========+========================================================================+
|
||||||
|
| description | string | description of chart set |
|
||||||
|
+-----------------+----------+------------------------------------------------------------------------+
|
||||||
|
| chart_group | array | A list of the ``metadata.name`` of each ``Chart`` to deploy. |
|
||||||
|
+-----------------+----------+------------------------------------------------------------------------+
|
||||||
|
| sequenced | bool | If ``true``, deploys each chart in sequence, else in parallel. |
|
||||||
|
| | | Default ``false``. |
|
||||||
|
+-----------------+----------+------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Chart Group Example
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
---
|
||||||
|
schema: armada/ChartGroup/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-group
|
||||||
|
data:
|
||||||
|
description: Deploys Simple Service
|
||||||
|
chart_group:
|
||||||
|
- chart1
|
||||||
|
- chart2
|
||||||
|
|
||||||
|
armada/Chart/v2
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Chart
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=================+==========+=======================================================================================+
|
||||||
|
| release | string | name of the release (Armada will prepend with ``release-prefix`` during processing) |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| namespace | string | namespace of your chart |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| wait | object | See `Wait`_. |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| protected | object | do not delete FAILED releases when encountered from previous run (provide the |
|
||||||
|
| | | 'continue_processing' bool to continue or halt execution (default: halt)) |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| test | object | See Test_. |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| upgrade | object | upgrade the chart managed by the armada yaml |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| delete | object | See Delete_. |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| values | object | (optional) override any default values in the charts |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| source | object | provide a path to a ``git repo``, ``local dir``, or ``tarball url`` chart |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
| dependencies | object | (optional) reference any chart dependencies before install |
|
||||||
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Wait
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+====================================================================+
|
||||||
|
| timeout | int | time (in seconds) to wait for chart to deploy |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| resources | array | Array of `Wait Resource`_ to wait on, with ``labels`` added to each|
|
||||||
|
| | | item. Defaults to pods and jobs (if any exist) matching ``labels``.|
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| labels | object | Base mapping of labels to wait on. They are added to any labels in |
|
||||||
|
| | | each item in the ``resources`` array. |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| native | boolean | See `Wait Native`_. |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Wait Resource
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+====================================================================+
|
||||||
|
| type | string | k8s resource type, supports: controllers ('deployment', |
|
||||||
|
| | | 'daemonset', 'statefulset'), 'pod', 'job' |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| labels | object | mapping of kubernetes resource labels |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| min\_ready | int | Only for controller ``type``s. Amount of pods in a controller |
|
||||||
|
| | string | which must be ready. Can be integer or percent string e.g. ``80%``.|
|
||||||
|
| | | Default ``100%``. |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Wait Native
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Config for the native ``helm (install|upgrade) --wait`` flag.
|
||||||
|
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+====================================================================+
|
||||||
|
| enabled | boolean | defaults to true |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
.. _test_v2:
|
||||||
|
|
||||||
|
Test
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
Run helm tests on the chart after install/upgrade.
|
||||||
|
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+====================================================================+
|
||||||
|
| enabled | bool | whether to enable/disable helm tests for this chart (default True) |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| timeout | int | time (in sec) to wait for completion of Helm tests |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
| options | object | See `Test Options`_. |
|
||||||
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Armada will attempt to run helm tests by default. They may be disabled by
|
||||||
|
setting the ``enabled`` key to ``False``.
|
||||||
|
|
||||||
|
Test Options
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Test options to pass through directly to helm.
|
||||||
|
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+===============================================================+
|
||||||
|
| cleanup | bool | cleanup test pods after test completion, defaults to false |
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If cleanup is ``true`` this prevents being able to debug a test in the event of failure.
|
||||||
|
|
||||||
|
Historically, the preferred way to achieve test cleanup has been to add a pre-upgrade delete
|
||||||
|
action on the test pod.
|
||||||
|
|
||||||
|
This still works, however it is usually no longer necessary as Armada now automatically
|
||||||
|
cleans up any test pods which match the ``wait.labels`` of the chart, immediately before
|
||||||
|
running tests. Similar suggestions have been made for how ``helm test --cleanup`` itself
|
||||||
|
ought to work (https://github.com/helm/helm/issues/3279).
|
||||||
|
|
||||||
|
Upgrade - Pre
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+===============================================================+
|
||||||
|
| pre | object | actions performed prior to updating a release |
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
|
||||||
|
Upgrade - Actions
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+===============================================================+
|
||||||
|
| delete | array | List of `Upgrade - Actions - Delete`_. |
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
|
||||||
|
Upgrade - Actions - Delete
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+===============================================================+
|
||||||
|
| type | string | type of kubernetes resource to delete |
|
||||||
|
| | | supported types are: 'pod', 'job', 'cronjob'. |
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
| labels | object | k:v mapping of labels to select Kubernetes resources |
|
||||||
|
+-------------+----------+---------------------------------------------------------------+
|
||||||
|
|
||||||
|
Chart Example
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-1
|
||||||
|
data:
|
||||||
|
release: blog-1
|
||||||
|
namespace: default
|
||||||
|
wait:
|
||||||
|
timeout: 100
|
||||||
|
protected:
|
||||||
|
continue_processing: false
|
||||||
|
test:
|
||||||
|
enabled: true
|
||||||
|
upgrade:
|
||||||
|
pre:
|
||||||
|
delete:
|
||||||
|
- name: test-job
|
||||||
|
type: job
|
||||||
|
labels:
|
||||||
|
foo: bar
|
||||||
|
component: bar
|
||||||
|
rak1: enabled
|
||||||
|
source:
|
||||||
|
type: git
|
||||||
|
location: https://github.com/namespace/repo
|
||||||
|
reference: master
|
||||||
|
|
||||||
|
Delete
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+===================================================================================+
|
||||||
|
| timeout | integer | time (in seconds) to wait for chart to be deleted |
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Source
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
| keyword | type | action |
|
||||||
|
+=============+==========+===================================================================================+
|
||||||
|
| type | string | source to build the chart: ``git``, ``local``, or ``tar`` |
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
| location | string | ``url`` or ``path`` to the chart's parent directory |
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
| subpath | string | (optional) relative path to target chart from parent (``.`` if not specified) |
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
| reference | string | (optional) branch, commit, or reference in the repo (``master`` if not specified) |
|
||||||
|
+-------------+----------+-----------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Source Example
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# type git
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-1
|
||||||
|
data:
|
||||||
|
release: blog-1
|
||||||
|
namespace: default
|
||||||
|
wait:
|
||||||
|
timeout: 100
|
||||||
|
labels:
|
||||||
|
component: blog
|
||||||
|
source:
|
||||||
|
type: git
|
||||||
|
location: https://github.com/namespace/repo
|
||||||
|
|
||||||
|
# type local
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-1
|
||||||
|
data:
|
||||||
|
release: blog-1
|
||||||
|
namespace: default
|
||||||
|
wait:
|
||||||
|
timeout: 100
|
||||||
|
source:
|
||||||
|
type: local
|
||||||
|
location: /path/to/charts
|
||||||
|
subpath: chart
|
||||||
|
reference: master
|
||||||
|
|
||||||
|
# type tar
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-1
|
||||||
|
data:
|
||||||
|
release: blog-1
|
||||||
|
namespace: default
|
||||||
|
wait:
|
||||||
|
timeout: 100
|
||||||
|
source:
|
||||||
|
type: tar
|
||||||
|
location: https://localhost:8879/charts/chart-0.1.0.tgz
|
||||||
|
subpath: mariadb
|
||||||
|
|
||||||
|
Simple Example
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-1
|
||||||
|
data:
|
||||||
|
release: blog-1
|
||||||
|
namespace: default
|
||||||
|
source:
|
||||||
|
type: git
|
||||||
|
location: https://github.com/namespace/repo
|
||||||
|
subpath: blog-1
|
||||||
|
reference: new-feat
|
||||||
|
---
|
||||||
|
schema: armada/ChartGroup/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-group
|
||||||
|
data:
|
||||||
|
description: Deploys Simple Service
|
||||||
|
chart_group:
|
||||||
|
- blog-1
|
||||||
|
---
|
||||||
|
schema: armada/Manifest/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: simple-armada
|
||||||
|
data:
|
||||||
|
release_prefix: armada
|
||||||
|
chart_groups:
|
||||||
|
- blog-group
|
||||||
|
|
||||||
|
Multichart Example
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-1
|
||||||
|
data:
|
||||||
|
release: blog-1
|
||||||
|
namespace: default
|
||||||
|
source:
|
||||||
|
type: git
|
||||||
|
location: https://github.com/namespace/repo
|
||||||
|
subpath: blog1
|
||||||
|
reference: master
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-2
|
||||||
|
data:
|
||||||
|
release: blog-2
|
||||||
|
namespace: default
|
||||||
|
source:
|
||||||
|
type: tar
|
||||||
|
location: https://github.com/namespace/repo/blog2.tgz
|
||||||
|
subpath: blog2
|
||||||
|
---
|
||||||
|
schema: armada/Chart/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-3
|
||||||
|
data:
|
||||||
|
release: blog-3
|
||||||
|
namespace: default
|
||||||
|
source:
|
||||||
|
type: local
|
||||||
|
location: /home/user/namespace/repo/blog3
|
||||||
|
---
|
||||||
|
schema: armada/ChartGroup/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-group-1
|
||||||
|
data:
|
||||||
|
description: Deploys Simple Service
|
||||||
|
chart_group:
|
||||||
|
- blog-2
|
||||||
|
---
|
||||||
|
schema: armada/ChartGroup/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: blog-group-2
|
||||||
|
data:
|
||||||
|
description: Deploys Simple Service
|
||||||
|
chart_group:
|
||||||
|
- blog-1
|
||||||
|
- blog-3
|
||||||
|
---
|
||||||
|
schema: armada/Manifest/v2
|
||||||
|
metadata:
|
||||||
|
schema: metadata/Document/v1
|
||||||
|
name: simple-armada
|
||||||
|
data:
|
||||||
|
release_prefix: armada
|
||||||
|
chart_groups:
|
||||||
|
- blog-group-1
|
||||||
|
- blog-group-2
|
||||||
|
|
||||||
|
References
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
For working examples please check the examples in our repo
|
||||||
|
`here <https://github.com/openstack/airship-armada/tree/master/examples>`__
|
|
@ -0,0 +1,25 @@
|
||||||
|
..
|
||||||
|
Copyright 2019 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
v2 (EXPERIMENTAL!)
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Contents:
|
||||||
|
|
||||||
|
document-authoring
|
||||||
|
schemas
|
|
@ -0,0 +1,114 @@
|
||||||
|
..
|
||||||
|
Copyright 2018 AT&T Intellectual Property.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
v2 Schemas
|
||||||
|
==========
|
||||||
|
|
||||||
|
Below are the schemas Armada uses to validate Charts, Chart Groups, and
|
||||||
|
Manifests.
|
||||||
|
|
||||||
|
Charts
|
||||||
|
------
|
||||||
|
|
||||||
|
Charts consist of the smallest building blocks in Armada. A ``Chart`` is
|
||||||
|
comparable to a Helm chart. Charts consist of all the labels, dependencies,
|
||||||
|
install and upgrade information, hooks and additional information needed to
|
||||||
|
convey to Tiller.
|
||||||
|
|
||||||
|
Chart Groups
|
||||||
|
------------
|
||||||
|
|
||||||
|
A ``Chart Group`` consists of a list of charts. ``Chart Group`` documents are
|
||||||
|
useful for managing a group of ``Chart`` documents together.
|
||||||
|
|
||||||
|
Manifests
|
||||||
|
---------
|
||||||
|
|
||||||
|
A ``Manifest`` is the largest building block in Armada. ``Manifest`` documents
|
||||||
|
are responsible for managing collections of ``Chart Group`` documents.
|
||||||
|
|
||||||
|
Validation Schemas
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
All schemas below are `Deckhand DataSchema`_ documents, which are essentially
|
||||||
|
JSON schemas, with additional metadata useful for Deckhand to perform
|
||||||
|
`layering`_ and `substitution`_.
|
||||||
|
|
||||||
|
The validation schemas below are used by Armada to validate all ingested
|
||||||
|
Charts, Chart Groups, and Manifests. Use the schemas below as models for
|
||||||
|
authoring Armada documents.
|
||||||
|
|
||||||
|
.. _Deckhand DataSchema: https://airship-deckhand.readthedocs.io/en/latest/document-types.html?highlight=dataschema#dataschema
|
||||||
|
.. _Helm charts: https://docs.helm.sh/developing_charts/
|
||||||
|
.. _layering: https://airship-deckhand.readthedocs.io/en/latest/layering.html
|
||||||
|
.. _substitution: https://airship-deckhand.readthedocs.io/en/latest/substitution.html
|
||||||
|
|
||||||
|
Schemas
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
* ``Chart`` schema.
|
||||||
|
|
||||||
|
JSON schema against which all documents with ``armada/Chart/v2``
|
||||||
|
``metadata.name`` are validated.
|
||||||
|
|
||||||
|
.. literalinclude::
|
||||||
|
../../../../../armada/schemas/armada-chart-schema-v2.yaml
|
||||||
|
:language: yaml
|
||||||
|
:lines: 15-
|
||||||
|
:caption: Schema for ``armada/Chart/v2`` documents.
|
||||||
|
|
||||||
|
This schema is used to sanity-check all ``Chart`` documents that are passed
|
||||||
|
to Armada.
|
||||||
|
|
||||||
|
* ``Chart Group`` schema.
|
||||||
|
|
||||||
|
JSON schema against which all documents with ``armada/Chart/v2``
|
||||||
|
``metadata.name`` are validated.
|
||||||
|
|
||||||
|
.. literalinclude::
|
||||||
|
../../../../../armada/schemas/armada-chartgroup-schema-v2.yaml
|
||||||
|
:language: yaml
|
||||||
|
:lines: 15-
|
||||||
|
:caption: Schema for ``armada/ChartGroup/v2`` documents.
|
||||||
|
|
||||||
|
This schema is used to sanity-check all ``Chart Group`` documents that are
|
||||||
|
passed to Armada.
|
||||||
|
|
||||||
|
* ``Manifest`` schema.
|
||||||
|
|
||||||
|
JSON schema against which all documents with ``armada/Manifest/v2``
|
||||||
|
``metadata.name`` are validated.
|
||||||
|
|
||||||
|
.. literalinclude::
|
||||||
|
../../../../../armada/schemas/armada-manifest-schema-v2.yaml
|
||||||
|
:language: yaml
|
||||||
|
:lines: 15-
|
||||||
|
:caption: Schema for ``armada/Manifest/v2`` documents.
|
||||||
|
|
||||||
|
This schema is used to sanity-check all ``Manifest`` documents that are passed
|
||||||
|
to Armada.
|
||||||
|
|
||||||
|
Authoring Guidelines
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
All Armada documents must use the ``deckhand/DataSchema/v1`` schema.
|
||||||
|
|
||||||
|
.. todo::
|
||||||
|
|
||||||
|
Expand on this section.
|
|
@ -10,7 +10,9 @@ Kubernetes Cluster
|
||||||
|
|
||||||
`Tiller Service <https://github.com/kubernetes/helm>`_
|
`Tiller Service <https://github.com/kubernetes/helm>`_
|
||||||
|
|
||||||
`Armada.yaml <https://airship-armada.readthedocs.io/en/latest/operations/guide-build-armada-yaml.html>`_
|
.. todo:: point this to v2 docs once they're stable
|
||||||
|
|
||||||
|
:ref:`Armada documents <document_authoring_v1>`
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,10 @@ Operations Guide
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
guide-build-armada-yaml
|
documents/index
|
||||||
guide-configure
|
guide-configure
|
||||||
guide-troubleshooting
|
guide-troubleshooting
|
||||||
guide-use-armada
|
guide-use-armada
|
||||||
documents
|
|
||||||
exceptions/index
|
exceptions/index
|
||||||
guide-helm-plugin
|
guide-helm-plugin
|
||||||
sampleconf
|
sampleconf
|
||||||
|
|
Loading…
Reference in New Issue