Revert "Airship 2 support features"
This reverts commit c75898cd6a
.
Airship 2 ended up using the Flux helm-controller instead:
https://github.com/fluxcd/helm-controller
So this is no longer needed. Removing it to get rid of tech
debt to ease introduction of Helm 3 support.
This retains the part of the commit which extracts the
chart download logic to its own handler as this is still useful.
Change-Id: Icb468be2d4916620fd78df250fd038ab58840182
This commit is contained in:
parent
b37417253f
commit
5f1ffbbbbe
21
.zuul.yaml
21
.zuul.yaml
@ -25,7 +25,6 @@
|
|||||||
- armada-docker-build-gate-ubuntu_xenial
|
- armada-docker-build-gate-ubuntu_xenial
|
||||||
- armada-docker-build-gate-opensuse
|
- armada-docker-build-gate-opensuse
|
||||||
- armada-airskiff-deploy
|
- armada-airskiff-deploy
|
||||||
- armada-airship2-integration
|
|
||||||
gate:
|
gate:
|
||||||
jobs:
|
jobs:
|
||||||
- openstack-tox-docs
|
- openstack-tox-docs
|
||||||
@ -129,26 +128,6 @@
|
|||||||
- ^releasenotes/.*$
|
- ^releasenotes/.*$
|
||||||
- ^swagger/.*$
|
- ^swagger/.*$
|
||||||
|
|
||||||
- job:
|
|
||||||
name: armada-airship2-integration
|
|
||||||
nodeset: armada-single-node
|
|
||||||
description: |
|
|
||||||
Deploy basic airship2 integration example using submitted Armada changes.
|
|
||||||
timeout: 9600
|
|
||||||
voting: false
|
|
||||||
pre-run:
|
|
||||||
- tools/gate/playbooks/git-config.yaml
|
|
||||||
run: tools/gate/playbooks/airship2-integration.yaml
|
|
||||||
post-run: tools/gate/playbooks/debug-report.yaml
|
|
||||||
required-projects:
|
|
||||||
- airship/treasuremap
|
|
||||||
irrelevant-files:
|
|
||||||
- ^.*\.rst$
|
|
||||||
- ^doc/.*$
|
|
||||||
- ^examples/.*$
|
|
||||||
- ^releasenotes/.*$
|
|
||||||
- ^swagger/.*$
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: armada-docker-publish-ubuntu_bionic
|
name: armada-docker-publish-ubuntu_bionic
|
||||||
timeout: 1800
|
timeout: 1800
|
||||||
|
@ -1,207 +0,0 @@
|
|||||||
# Copyright 2020 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 click
|
|
||||||
from oslo_config import cfg
|
|
||||||
import prometheus_client
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
from armada.cli import CliAction
|
|
||||||
from armada.exceptions.source_exceptions import InvalidPathException
|
|
||||||
from armada.handlers import metrics
|
|
||||||
from armada.handlers.chart_deploy import ChartDeploy
|
|
||||||
from armada.handlers.chart_download import ChartDownload
|
|
||||||
from armada.handlers.document import ReferenceResolver
|
|
||||||
from armada.handlers.lock import lock_and_thread
|
|
||||||
from armada.handlers.manifest import Chart
|
|
||||||
from armada.handlers.tiller import Tiller
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
|
||||||
def apply_chart():
|
|
||||||
""" Apply chart to cluster
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
DESC = """
|
|
||||||
This command installs and updates an Armada chart.
|
|
||||||
|
|
||||||
[LOCATION] must be a relative path to Armada Chart or a reference
|
|
||||||
to an Armada Chart kubernetes CR which has the same format, except as
|
|
||||||
noted in the v2 document authoring documentation.
|
|
||||||
|
|
||||||
To install or upgrade a chart, run:
|
|
||||||
|
|
||||||
\b
|
|
||||||
$ armada apply_chart --release-prefix=armada my-chart.yaml
|
|
||||||
$ armada apply_chart --release-prefix=armada \
|
|
||||||
kube:armadacharts/my-namespace/my-chart
|
|
||||||
"""
|
|
||||||
|
|
||||||
SHORT_DESC = "Command deploys a chart."
|
|
||||||
|
|
||||||
|
|
||||||
@apply_chart.command(name='apply_chart', help=DESC, short_help=SHORT_DESC)
|
|
||||||
@click.argument('location')
|
|
||||||
@click.option(
|
|
||||||
'--release-prefix',
|
|
||||||
help="Prefix to prepend to chart release name.",
|
|
||||||
required=True)
|
|
||||||
@click.option(
|
|
||||||
'--disable-update-post',
|
|
||||||
help="Disable post-update Tiller operations.",
|
|
||||||
is_flag=True)
|
|
||||||
@click.option(
|
|
||||||
'--disable-update-pre',
|
|
||||||
help="Disable pre-update Tiller operations.",
|
|
||||||
is_flag=True)
|
|
||||||
@click.option(
|
|
||||||
'--metrics-output',
|
|
||||||
help=(
|
|
||||||
"Output path for prometheus metric data, should end in .prom. By "
|
|
||||||
"default, no metric data is output."),
|
|
||||||
default=None)
|
|
||||||
@click.option('--tiller-host', help="Tiller host IP.", default=None)
|
|
||||||
@click.option(
|
|
||||||
'--tiller-port', help="Tiller host port.", type=int, default=None)
|
|
||||||
@click.option(
|
|
||||||
'--tiller-namespace',
|
|
||||||
'-tn',
|
|
||||||
help="Tiller namespace.",
|
|
||||||
type=str,
|
|
||||||
default=None)
|
|
||||||
@click.option(
|
|
||||||
'--timeout',
|
|
||||||
help="Specifies time to wait for each chart to fully "
|
|
||||||
"finish deploying.",
|
|
||||||
type=int)
|
|
||||||
@click.option(
|
|
||||||
'--wait',
|
|
||||||
help=(
|
|
||||||
"Force Tiller to wait until the chart is deployed, "
|
|
||||||
"rather than using the chart's specified wait policy. "
|
|
||||||
"This is equivalent to sequenced chartgroups."),
|
|
||||||
is_flag=True)
|
|
||||||
@click.option(
|
|
||||||
'--target-chart',
|
|
||||||
help=(
|
|
||||||
"The target chart to deploy. Required for specifying "
|
|
||||||
"which chart to deploy when multiple are available."),
|
|
||||||
default=None)
|
|
||||||
@click.option('--bearer-token', help="User Bearer token", default=None)
|
|
||||||
@click.option('--debug', help="Enable debug logging.", is_flag=True)
|
|
||||||
@click.pass_context
|
|
||||||
def apply_chart(
|
|
||||||
ctx, location, release_prefix, disable_update_post, disable_update_pre,
|
|
||||||
metrics_output, tiller_host, tiller_port, tiller_namespace, timeout,
|
|
||||||
wait, target_chart, bearer_token, debug):
|
|
||||||
CONF.debug = debug
|
|
||||||
ApplyChart(
|
|
||||||
ctx, location, release_prefix, disable_update_post, disable_update_pre,
|
|
||||||
metrics_output, tiller_host, tiller_port, tiller_namespace, timeout,
|
|
||||||
wait, target_chart, bearer_token).safe_invoke()
|
|
||||||
|
|
||||||
|
|
||||||
class ApplyChart(CliAction):
|
|
||||||
def __init__(
|
|
||||||
self, ctx, location, release_prefix, disable_update_post,
|
|
||||||
disable_update_pre, metrics_output, tiller_host, tiller_port,
|
|
||||||
tiller_namespace, timeout, wait, target_chart, bearer_token):
|
|
||||||
super(ApplyChart, self).__init__()
|
|
||||||
self.ctx = ctx
|
|
||||||
self.release_prefix = release_prefix
|
|
||||||
# Filename can also be a URL reference
|
|
||||||
self.location = location
|
|
||||||
self.disable_update_post = disable_update_post
|
|
||||||
self.disable_update_pre = disable_update_pre
|
|
||||||
self.metrics_output = metrics_output
|
|
||||||
self.tiller_host = tiller_host
|
|
||||||
self.tiller_port = tiller_port
|
|
||||||
self.tiller_namespace = tiller_namespace
|
|
||||||
self.timeout = timeout
|
|
||||||
self.target_chart = target_chart
|
|
||||||
self.bearer_token = bearer_token
|
|
||||||
|
|
||||||
def output(self, resp):
|
|
||||||
for result in resp:
|
|
||||||
if not resp[result] and not result == 'diff':
|
|
||||||
self.logger.info('Did not perform chart %s(s)', result)
|
|
||||||
elif result == 'diff' and not resp[result]:
|
|
||||||
self.logger.info('No release changes detected')
|
|
||||||
|
|
||||||
ch = resp[result]
|
|
||||||
if not result == 'diff':
|
|
||||||
msg = 'Chart {} took action: {}'.format(ch, result)
|
|
||||||
if result == 'protected':
|
|
||||||
msg += ' and requires operator attention.'
|
|
||||||
elif result == 'purge':
|
|
||||||
msg += ' before install/upgrade.'
|
|
||||||
self.logger.info(msg)
|
|
||||||
else:
|
|
||||||
self.logger.info('Chart/values diff: %s', ch)
|
|
||||||
|
|
||||||
def invoke(self):
|
|
||||||
with Tiller(tiller_host=self.tiller_host, tiller_port=self.tiller_port,
|
|
||||||
tiller_namespace=self.tiller_namespace,
|
|
||||||
bearer_token=self.bearer_token) as tiller:
|
|
||||||
|
|
||||||
try:
|
|
||||||
doc_data = ReferenceResolver.resolve_reference(
|
|
||||||
self.location, k8s=tiller.k8s)
|
|
||||||
documents = list()
|
|
||||||
for d in doc_data:
|
|
||||||
documents.extend(list(yaml.safe_load_all(d.decode())))
|
|
||||||
except InvalidPathException as ex:
|
|
||||||
self.logger.error(str(ex))
|
|
||||||
return
|
|
||||||
except yaml.YAMLError as yex:
|
|
||||||
self.logger.error("Invalid YAML found: %s" % str(yex))
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
resp = self.handle(documents, tiller)
|
|
||||||
self.output(resp)
|
|
||||||
finally:
|
|
||||||
if self.metrics_output:
|
|
||||||
path = self.metrics_output
|
|
||||||
self.logger.info(
|
|
||||||
'Storing metrics output in path: {}'.format(path))
|
|
||||||
prometheus_client.write_to_textfile(path, metrics.REGISTRY)
|
|
||||||
|
|
||||||
def handle(self, documents, tiller):
|
|
||||||
chart = Chart(documents, target_chart=self.target_chart).get_chart()
|
|
||||||
|
|
||||||
lock_name = 'chart-{}'.format(chart['metadata']['name'])
|
|
||||||
|
|
||||||
@lock_and_thread(lock_name)
|
|
||||||
def _handle():
|
|
||||||
chart_download = ChartDownload()
|
|
||||||
try:
|
|
||||||
chart_download.get_chart(chart)
|
|
||||||
chart_deploy = ChartDeploy(
|
|
||||||
None, self.disable_update_pre, self.disable_update_post, 1,
|
|
||||||
1, self.timeout, tiller)
|
|
||||||
|
|
||||||
# TODO: Only get release with matching name.
|
|
||||||
known_releases = tiller.list_releases()
|
|
||||||
|
|
||||||
return chart_deploy.execute(
|
|
||||||
chart, None, self.release_prefix, known_releases, 1)
|
|
||||||
finally:
|
|
||||||
chart_download.cleanup()
|
|
||||||
|
|
||||||
return _handle()
|
|
@ -47,16 +47,14 @@ class ChartDeploy(object):
|
|||||||
def execute(
|
def execute(
|
||||||
self, ch, cg_test_all_charts, prefix, known_releases, concurrency):
|
self, ch, cg_test_all_charts, prefix, known_releases, concurrency):
|
||||||
chart_name = ch['metadata']['name']
|
chart_name = ch['metadata']['name']
|
||||||
manifest_name = self.manifest['metadata'][
|
manifest_name = self.manifest['metadata']['name']
|
||||||
'name'] if self.manifest else ''
|
|
||||||
with metrics.CHART_HANDLE.get_context(concurrency, manifest_name,
|
with metrics.CHART_HANDLE.get_context(concurrency, manifest_name,
|
||||||
chart_name):
|
chart_name):
|
||||||
return self._execute(
|
return self._execute(
|
||||||
ch, cg_test_all_charts, prefix, known_releases)
|
ch, cg_test_all_charts, prefix, known_releases)
|
||||||
|
|
||||||
def _execute(self, ch, cg_test_all_charts, prefix, known_releases):
|
def _execute(self, ch, cg_test_all_charts, prefix, known_releases):
|
||||||
manifest_name = self.manifest['metadata'][
|
manifest_name = self.manifest['metadata']['name']
|
||||||
'name'] if self.manifest else ''
|
|
||||||
chart = ch[const.KEYWORD_DATA]
|
chart = ch[const.KEYWORD_DATA]
|
||||||
chart_name = ch['metadata']['name']
|
chart_name = ch['metadata']['name']
|
||||||
namespace = chart.get('namespace')
|
namespace = chart.get('namespace')
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from oslo_log import log as logging
|
|
||||||
import requests
|
import requests
|
||||||
import yaml
|
from oslo_log import log as logging
|
||||||
from kubernetes.client.rest import ApiException
|
|
||||||
|
|
||||||
from armada.exceptions.source_exceptions import InvalidPathException
|
from armada.exceptions.source_exceptions import InvalidPathException
|
||||||
from armada.utils import keystone as ks_utils
|
from armada.utils import keystone as ks_utils
|
||||||
@ -32,7 +30,7 @@ class ReferenceResolver(object):
|
|||||||
"""Class for handling different data references to resolve the data."""
|
"""Class for handling different data references to resolve the data."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_reference(cls, design_ref, k8s=None):
|
def resolve_reference(cls, design_ref):
|
||||||
"""Resolve a reference to a design document.
|
"""Resolve a reference to a design document.
|
||||||
|
|
||||||
Locate a schema handler based on the URI scheme of the data reference
|
Locate a schema handler based on the URI scheme of the data reference
|
||||||
@ -53,16 +51,10 @@ class ReferenceResolver(object):
|
|||||||
|
|
||||||
# when scheme is a empty string assume it is a local
|
# when scheme is a empty string assume it is a local
|
||||||
# file path
|
# file path
|
||||||
scheme = design_uri.scheme or 'file'
|
if design_uri.scheme == '':
|
||||||
handler = cls.scheme_handlers.get(scheme, None)
|
handler = cls.scheme_handlers.get('file')
|
||||||
handler = handler.__get__(None, cls)
|
else:
|
||||||
if design_uri.scheme == 'kube':
|
handler = cls.scheme_handlers.get(design_uri.scheme, None)
|
||||||
handler_2 = handler
|
|
||||||
|
|
||||||
def handler_1(design_uri):
|
|
||||||
return handler_2(design_uri, k8s)
|
|
||||||
|
|
||||||
handler = handler_1
|
|
||||||
|
|
||||||
if handler is None:
|
if handler is None:
|
||||||
raise InvalidPathException(
|
raise InvalidPathException(
|
||||||
@ -79,50 +71,6 @@ class ReferenceResolver(object):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resolve_reference_kube(cls, design_uri, k8s):
|
|
||||||
"""Retrieve design documents from kubernetes crd.
|
|
||||||
|
|
||||||
Return the result of converting the CRD to the armada/Chart/v2 schema.
|
|
||||||
|
|
||||||
:param design_uri: Tuple as returned by urllib.parse
|
|
||||||
for the design reference
|
|
||||||
"""
|
|
||||||
if design_uri.path != '':
|
|
||||||
parts = design_uri.path.split('/')
|
|
||||||
if len(parts) != 3:
|
|
||||||
raise InvalidPathException(
|
|
||||||
"Invalid kubernetes custom resource path segment count {} "
|
|
||||||
"for '{}', expected <kind>/<namespace>/<name>".format(
|
|
||||||
len(parts), design_uri.path))
|
|
||||||
plural, namespace, name = parts
|
|
||||||
if plural != 'armadacharts':
|
|
||||||
raise InvalidPathException(
|
|
||||||
"Invalid kubernetes custom resource kind '{}' for '{}', "
|
|
||||||
"only 'armadacharts' are supported".format(
|
|
||||||
plural, design_uri.path))
|
|
||||||
|
|
||||||
try:
|
|
||||||
cr = k8s.read_custom_resource(
|
|
||||||
group='armada.airshipit.org',
|
|
||||||
version='v1alpha1',
|
|
||||||
namespace=namespace,
|
|
||||||
plural=plural,
|
|
||||||
name=name)
|
|
||||||
|
|
||||||
except ApiException as err:
|
|
||||||
if err.status == 404:
|
|
||||||
raise InvalidPathException(
|
|
||||||
"Kubernetes custom resource not found: plural='{}', "
|
|
||||||
"namespace='{}', name='{}', api exception=\n{}".format(
|
|
||||||
plural, namespace, name, err.message))
|
|
||||||
raise
|
|
||||||
|
|
||||||
cr['schema'] = 'armada/Chart/v2'
|
|
||||||
spec = cr.pop('spec')
|
|
||||||
cr['data'] = spec
|
|
||||||
return yaml.safe_dump(cr, encoding='utf-8')
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_reference_http(cls, design_uri):
|
def resolve_reference_http(cls, design_uri):
|
||||||
"""Retrieve design documents from http/https endpoints.
|
"""Retrieve design documents from http/https endpoints.
|
||||||
@ -186,7 +134,6 @@ class ReferenceResolver(object):
|
|||||||
return resp.content
|
return resp.content
|
||||||
|
|
||||||
scheme_handlers = {
|
scheme_handlers = {
|
||||||
'kube': resolve_reference_kube,
|
|
||||||
'http': resolve_reference_http,
|
'http': resolve_reference_http,
|
||||||
'file': resolve_reference_file,
|
'file': resolve_reference_file,
|
||||||
'https': resolve_reference_http,
|
'https': resolve_reference_http,
|
||||||
|
@ -22,12 +22,56 @@ from armada.handlers import schema
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Doc(object):
|
class Manifest(object):
|
||||||
def __init__(self, documents):
|
def __init__(self, documents, target_manifest=None):
|
||||||
self.documents = deepcopy(documents)
|
"""Instantiates a Manifest object.
|
||||||
self.charts, self.groups, self.manifests = self._find_documents()
|
|
||||||
|
|
||||||
def _find_documents(self):
|
An Armada Manifest expects that at least one of each of the following
|
||||||
|
be included in ``documents``:
|
||||||
|
|
||||||
|
* A document with schema "armada/Chart/v1"
|
||||||
|
* A document with schema "armada/ChartGroup/v1"
|
||||||
|
|
||||||
|
And only one document of the following is allowed:
|
||||||
|
|
||||||
|
* A document with schema "armada/Manifest/v1"
|
||||||
|
|
||||||
|
If multiple documents with schema "armada/Manifest/v1" are provided,
|
||||||
|
specify ``target_manifest`` to select the target one.
|
||||||
|
|
||||||
|
:param List[dict] documents: Documents out of which to build the
|
||||||
|
Armada Manifest.
|
||||||
|
:param str target_manifest: The target manifest to use when multiple
|
||||||
|
documents with "armada/Manifest/v1" are contained in
|
||||||
|
``documents``. Default is None.
|
||||||
|
:raises ManifestException: If the expected number of document types
|
||||||
|
are not found or if the document types are missing required
|
||||||
|
properties.
|
||||||
|
"""
|
||||||
|
self.documents = deepcopy(documents)
|
||||||
|
self.charts, self.groups, manifests = self._find_documents(
|
||||||
|
target_manifest)
|
||||||
|
|
||||||
|
if len(manifests) > 1:
|
||||||
|
error = (
|
||||||
|
'Multiple manifests are not supported. Ensure that the '
|
||||||
|
'`target_manifest` option is set to specify the target '
|
||||||
|
'manifest')
|
||||||
|
LOG.error(error)
|
||||||
|
raise exceptions.ManifestException(details=error)
|
||||||
|
else:
|
||||||
|
self.manifest = manifests[0] if manifests else None
|
||||||
|
|
||||||
|
if not all([self.charts, self.groups, self.manifest]):
|
||||||
|
expected_schemas = [schema.TYPE_CHART, schema.TYPE_CHARTGROUP]
|
||||||
|
error = (
|
||||||
|
'Documents must include at least one of each of {} '
|
||||||
|
'and only one {}').format(
|
||||||
|
expected_schemas, schema.TYPE_MANIFEST)
|
||||||
|
LOG.error(error)
|
||||||
|
raise exceptions.ManifestException(details=error)
|
||||||
|
|
||||||
|
def _find_documents(self, target_manifest=None):
|
||||||
"""Returns the chart documents, chart group documents,
|
"""Returns the chart documents, chart group documents,
|
||||||
and Armada manifest
|
and Armada manifest
|
||||||
|
|
||||||
@ -53,44 +97,14 @@ class Doc(object):
|
|||||||
if schema_info.type == schema.TYPE_CHARTGROUP:
|
if schema_info.type == schema.TYPE_CHARTGROUP:
|
||||||
groups.append(document)
|
groups.append(document)
|
||||||
if schema_info.type == schema.TYPE_MANIFEST:
|
if schema_info.type == schema.TYPE_MANIFEST:
|
||||||
manifests.append(document)
|
manifest_name = document.get('metadata', {}).get('name')
|
||||||
|
if target_manifest:
|
||||||
|
if manifest_name == target_manifest:
|
||||||
|
manifests.append(document)
|
||||||
|
else:
|
||||||
|
manifests.append(document)
|
||||||
return charts, groups, manifests
|
return charts, groups, manifests
|
||||||
|
|
||||||
def _get_target_doc(self, sch, documents, target, target_arg_name):
|
|
||||||
"""Validates there is exactly one document of a given schema and
|
|
||||||
optionally name and returns it.
|
|
||||||
|
|
||||||
:param sch: Schema which corresponds to `documents`.
|
|
||||||
:param documents: Documents which correspond to `sch`.
|
|
||||||
:param target: The target document name of schema `sch` to return.
|
|
||||||
Default is None.
|
|
||||||
:raises ManifestException: If `target` is None and multiple `documents`
|
|
||||||
are passed, or if no documents are found matching the parameters.
|
|
||||||
"""
|
|
||||||
candidates = []
|
|
||||||
for manifest in documents:
|
|
||||||
if target:
|
|
||||||
manifest_name = manifest.get('metadata', {}).get('name')
|
|
||||||
if manifest_name == target:
|
|
||||||
candidates.append(manifest)
|
|
||||||
else:
|
|
||||||
candidates.append(manifest)
|
|
||||||
|
|
||||||
if len(candidates) > 1:
|
|
||||||
error = (
|
|
||||||
'Multiple {} documents are not supported. Ensure that the '
|
|
||||||
'`{}` option is set to specify the target one').format(
|
|
||||||
sch, target_arg_name)
|
|
||||||
LOG.error(error)
|
|
||||||
raise exceptions.ManifestException(details=error)
|
|
||||||
|
|
||||||
if not candidates:
|
|
||||||
error = 'Documents must include at least one {}'.format(sch)
|
|
||||||
LOG.error(error)
|
|
||||||
raise exceptions.ManifestException(details=error)
|
|
||||||
|
|
||||||
return candidates[0]
|
|
||||||
|
|
||||||
def find_chart_document(self, name):
|
def find_chart_document(self, name):
|
||||||
"""Returns a chart document with the specified name
|
"""Returns a chart document with the specified name
|
||||||
|
|
||||||
@ -107,6 +121,22 @@ class Doc(object):
|
|||||||
details='Could not find {} named "{}"'.format(
|
details='Could not find {} named "{}"'.format(
|
||||||
schema.TYPE_CHART, name))
|
schema.TYPE_CHART, name))
|
||||||
|
|
||||||
|
def find_chart_group_document(self, name):
|
||||||
|
"""Returns a chart group document with the specified name
|
||||||
|
|
||||||
|
:param str name: name of the desired chart group document
|
||||||
|
:returns: The requested chart group document
|
||||||
|
:rtype: dict
|
||||||
|
:raises ManifestException: If a chart
|
||||||
|
group document with the specified name is not found
|
||||||
|
"""
|
||||||
|
for group in self.groups:
|
||||||
|
if group.get('metadata', {}).get('name') == name:
|
||||||
|
return group
|
||||||
|
raise exceptions.BuildChartGroupException(
|
||||||
|
details='Could not find {} named "{}"'.format(
|
||||||
|
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``.
|
||||||
|
|
||||||
@ -134,90 +164,6 @@ class Doc(object):
|
|||||||
else:
|
else:
|
||||||
return chart
|
return chart
|
||||||
|
|
||||||
|
|
||||||
class Chart(Doc):
|
|
||||||
def __init__(self, documents, target_chart=None):
|
|
||||||
"""A Chart expects the following be included in ``documents``:
|
|
||||||
|
|
||||||
* A document with schema "armada/Chart/v1"
|
|
||||||
|
|
||||||
If multiple Charts are provided, specify ``target_chart`` to select the
|
|
||||||
target one.
|
|
||||||
|
|
||||||
:param documents: Documents out of which to build the
|
|
||||||
Chart.
|
|
||||||
:param target_chart: The target Chart to use when multiple
|
|
||||||
Charts are contained in ``documents``. Default is None.
|
|
||||||
:raises ManifestException: If the expected number of document types
|
|
||||||
are not found or if the document types are missing required
|
|
||||||
properties.
|
|
||||||
"""
|
|
||||||
super(Chart, self).__init__(documents)
|
|
||||||
self.chart = self._get_target_doc(
|
|
||||||
schema.TYPE_CHART, self.documents, target_chart, 'target_chart')
|
|
||||||
|
|
||||||
def get_chart(self):
|
|
||||||
"""Builds the Chart
|
|
||||||
|
|
||||||
:returns: The Chart.
|
|
||||||
:rtype: dict
|
|
||||||
"""
|
|
||||||
self.build_chart_deps(self.chart)
|
|
||||||
return self.chart
|
|
||||||
|
|
||||||
|
|
||||||
class Manifest(Doc):
|
|
||||||
def __init__(self, documents, target_manifest=None):
|
|
||||||
"""An Armada Manifest expects that at least one of each of the following
|
|
||||||
be included in ``documents``:
|
|
||||||
|
|
||||||
* A document with schema "armada/Chart/v1"
|
|
||||||
* A document with schema "armada/ChartGroup/v1"
|
|
||||||
|
|
||||||
And only one document of the following is allowed:
|
|
||||||
|
|
||||||
* A document with schema "armada/Manifest/v1"
|
|
||||||
|
|
||||||
If multiple documents with schema "armada/Manifest/v1" are provided,
|
|
||||||
specify ``target_manifest`` to select the target one.
|
|
||||||
|
|
||||||
:param List[dict] documents: Documents out of which to build the
|
|
||||||
Armada Manifest.
|
|
||||||
:param str target_manifest: The target manifest to use when multiple
|
|
||||||
documents with "armada/Manifest/v1" are contained in
|
|
||||||
``documents``. Default is None.
|
|
||||||
:raises ManifestException: If the expected number of document types
|
|
||||||
are not found or if the document types are missing required
|
|
||||||
properties.
|
|
||||||
"""
|
|
||||||
super(Manifest, self).__init__(documents)
|
|
||||||
self.manifest = self._get_target_doc(
|
|
||||||
schema.TYPE_MANIFEST, self.manifests, target_manifest,
|
|
||||||
'target_manifest')
|
|
||||||
|
|
||||||
if not all([self.charts, self.groups]):
|
|
||||||
expected_schemas = [schema.TYPE_CHART, schema.TYPE_CHARTGROUP]
|
|
||||||
error = 'Documents must include at least one of each of {}'.format(
|
|
||||||
expected_schemas)
|
|
||||||
LOG.error(error)
|
|
||||||
raise exceptions.ManifestException(details=error)
|
|
||||||
|
|
||||||
def find_chart_group_document(self, name):
|
|
||||||
"""Returns a chart group document with the specified name
|
|
||||||
|
|
||||||
:param str name: name of the desired chart group document
|
|
||||||
:returns: The requested chart group document
|
|
||||||
:rtype: dict
|
|
||||||
:raises ManifestException: If a chart
|
|
||||||
group document with the specified name is not found
|
|
||||||
"""
|
|
||||||
for group in self.groups:
|
|
||||||
if group.get('metadata', {}).get('name') == name:
|
|
||||||
return group
|
|
||||||
raise exceptions.BuildChartGroupException(
|
|
||||||
details='Could not find {} named "{}"'.format(
|
|
||||||
schema.TYPE_CHARTGROUP, name))
|
|
||||||
|
|
||||||
def build_chart_group(self, chart_group):
|
def build_chart_group(self, chart_group):
|
||||||
"""Builds the chart dependencies for`charts`chart group``.
|
"""Builds the chart dependencies for`charts`chart group``.
|
||||||
|
|
||||||
|
@ -61,12 +61,6 @@ class ChartWait():
|
|||||||
schema_info = get_schema_info(self.chart['schema'])
|
schema_info = get_schema_info(self.chart['schema'])
|
||||||
|
|
||||||
resources = self.wait_config.get('resources')
|
resources = self.wait_config.get('resources')
|
||||||
|
|
||||||
# wait.resources can be set to [] to disable all resource types, so
|
|
||||||
# don't override with defaults
|
|
||||||
if resources is None:
|
|
||||||
resources = self.wait_config.get('resources_list')
|
|
||||||
|
|
||||||
if isinstance(resources, list):
|
if isinstance(resources, list):
|
||||||
# Explicit resource config list provided.
|
# Explicit resource config list provided.
|
||||||
resources_list = resources
|
resources_list = resources
|
||||||
|
@ -19,7 +19,6 @@ from oslo_config import cfg
|
|||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
from armada.cli.apply import apply_create
|
from armada.cli.apply import apply_create
|
||||||
from armada.cli.apply_chart import apply_chart
|
|
||||||
from armada.cli.delete import delete_charts
|
from armada.cli.delete import delete_charts
|
||||||
from armada.cli.rollback import rollback_charts
|
from armada.cli.rollback import rollback_charts
|
||||||
from armada.cli.test import test_charts
|
from armada.cli.test import test_charts
|
||||||
@ -50,7 +49,6 @@ def main(ctx, debug, api, url, token):
|
|||||||
|
|
||||||
\b
|
\b
|
||||||
$ armada apply
|
$ armada apply
|
||||||
$ armada apply_chart
|
|
||||||
$ armada delete
|
$ armada delete
|
||||||
$ armada rollback
|
$ armada rollback
|
||||||
$ armada test
|
$ armada test
|
||||||
@ -90,7 +88,6 @@ def main(ctx, debug, api, url, token):
|
|||||||
|
|
||||||
|
|
||||||
main.add_command(apply_create)
|
main.add_command(apply_create)
|
||||||
main.add_command(apply_chart)
|
|
||||||
main.add_command(delete_charts)
|
main.add_command(delete_charts)
|
||||||
main.add_command(rollback_charts)
|
main.add_command(rollback_charts)
|
||||||
main.add_command(test_charts)
|
main.add_command(test_charts)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from armada import exceptions
|
from armada import exceptions
|
||||||
@ -117,7 +117,7 @@ class ManifestTestCase(testtools.TestCase):
|
|||||||
def test_find_documents(self):
|
def test_find_documents(self):
|
||||||
armada_manifest = manifest.Manifest(self.documents)
|
armada_manifest = manifest.Manifest(self.documents)
|
||||||
chart_documents, chart_groups, manifests = armada_manifest. \
|
chart_documents, chart_groups, manifests = armada_manifest. \
|
||||||
_find_documents()
|
_find_documents(target_manifest='armada-manifest')
|
||||||
|
|
||||||
# checking if all the chart documents are present
|
# checking if all the chart documents are present
|
||||||
self.assertIsInstance(chart_documents, list)
|
self.assertIsInstance(chart_documents, list)
|
||||||
@ -344,8 +344,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
|||||||
documents = copy.deepcopy(self.documents)
|
documents = copy.deepcopy(self.documents)
|
||||||
documents.append(documents[-1]) # Copy the last manifest.
|
documents.append(documents[-1]) # Copy the last manifest.
|
||||||
|
|
||||||
error_re = r'Multiple {} documents are not supported.*'.format(
|
error_re = r'Multiple manifests are not supported.*'
|
||||||
schema.TYPE_MANIFEST)
|
|
||||||
self.assertRaisesRegexp(
|
self.assertRaisesRegexp(
|
||||||
exceptions.ManifestException, error_re, manifest.Manifest,
|
exceptions.ManifestException, error_re, manifest.Manifest,
|
||||||
documents)
|
documents)
|
||||||
@ -356,8 +355,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
|||||||
documents = copy.deepcopy(self.documents)
|
documents = copy.deepcopy(self.documents)
|
||||||
documents.append(documents[-1]) # Copy the last manifest.
|
documents.append(documents[-1]) # Copy the last manifest.
|
||||||
|
|
||||||
error_re = r'Multiple {} documents are not supported.*'.format(
|
error_re = r'Multiple manifests are not supported.*'
|
||||||
schema.TYPE_MANIFEST)
|
|
||||||
self.assertRaisesRegexp(
|
self.assertRaisesRegexp(
|
||||||
exceptions.ManifestException,
|
exceptions.ManifestException,
|
||||||
error_re,
|
error_re,
|
||||||
@ -366,7 +364,9 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
|||||||
target_manifest='armada-manifest')
|
target_manifest='armada-manifest')
|
||||||
|
|
||||||
def _assert_missing_documents_raises(self, documents):
|
def _assert_missing_documents_raises(self, documents):
|
||||||
error_re = ('.*Documents must include at least one of each of .*')
|
error_re = (
|
||||||
|
'.*Documents must include at least one of each of .* and '
|
||||||
|
'only one .*')
|
||||||
self.assertRaisesRegexp(
|
self.assertRaisesRegexp(
|
||||||
exceptions.ManifestException, error_re, manifest.Manifest,
|
exceptions.ManifestException, error_re, manifest.Manifest,
|
||||||
documents)
|
documents)
|
||||||
@ -374,11 +374,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
|||||||
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 include at least one {}'.format(
|
self._assert_missing_documents_raises(self.documents[:-1])
|
||||||
schema.TYPE_MANIFEST)
|
|
||||||
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
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
Armada - Apply Chart
|
|
||||||
====================
|
|
||||||
|
|
||||||
|
|
||||||
Commands
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
Usage: armada apply_chart [OPTIONS] [LOCATION]
|
|
||||||
|
|
||||||
This command installs and updates an Armada chart.
|
|
||||||
|
|
||||||
[LOCATION] must be a relative path to Armada Chart or a reference
|
|
||||||
to an Armada Chart kubernetes CR which has the same format, except as
|
|
||||||
noted in the :ref:`v2 document authoring documentation <document_authoring_v2>`.
|
|
||||||
|
|
||||||
To install or upgrade a chart, run:
|
|
||||||
|
|
||||||
$ armada apply_chart --release-prefix=armada my-chart.yaml
|
|
||||||
$ armada apply_chart --release-prefix=armada kube:armadacharts/my-namespace/my-chart
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--release-prefix TEXT Release prefix to use. [required]
|
|
||||||
--disable-update-post Disable post-update Tiller operations.
|
|
||||||
--disable-update-pre Disable pre-update Tiller operations.
|
|
||||||
--metrics-output TEXT Output path for prometheus metric data, should
|
|
||||||
end in .prom. By default, no metric data is
|
|
||||||
output.
|
|
||||||
--tiller-host TEXT Tiller host IP.
|
|
||||||
--tiller-port INTEGER Tiller host port.
|
|
||||||
-tn, --tiller-namespace TEXT Tiller namespace.
|
|
||||||
--timeout INTEGER Specifies time to wait for each chart to fully
|
|
||||||
finish deploying.
|
|
||||||
--wait Force Tiller to wait until the chart is
|
|
||||||
deployed, rather than using the charts
|
|
||||||
specified wait policy. This is equivalent to
|
|
||||||
sequenced chartgroups.
|
|
||||||
--target-chart TEXT The target chart to deploy. Required for
|
|
||||||
specifying which chart to deploy when multiple
|
|
||||||
are available.
|
|
||||||
--bearer-token TEXT User Bearer token
|
|
||||||
--debug Enable debug logging.
|
|
||||||
--help Show this message and exit.
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
The apply_chart command will deploy an armada chart definition, installing or
|
|
||||||
updating as appropriate.
|
|
||||||
|
|
||||||
``armada apply_chart --release-prefix=armada my-chart.yaml [--debug]``
|
|
||||||
``armada apply_chart --release-prefix=armada kube:armadacharts/my-namespace/my-chart [--debug]``
|
|
@ -11,7 +11,6 @@ Commands Guide
|
|||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
apply.rst
|
apply.rst
|
||||||
apply_chart.rst
|
|
||||||
rollback.rst
|
rollback.rst
|
||||||
test.rst
|
test.rst
|
||||||
tiller.rst
|
tiller.rst
|
||||||
|
@ -124,7 +124,6 @@ Chart
|
|||||||
| dependencies | object | (optional) Override the `builtin chart dependencies`_ with a list of Chart documents |
|
| dependencies | object | (optional) Override the `builtin chart dependencies`_ with a list of Chart documents |
|
||||||
| | | to use as dependencies instead. |
|
| | | to use as dependencies instead. |
|
||||||
| | | NOTE: Builtin ".tgz" dependencies are not yet supported. |
|
| | | NOTE: Builtin ".tgz" dependencies are not yet supported. |
|
||||||
| | | NOTE: This field is not supported in the ArmadaChart CRD. |
|
|
||||||
+-----------------+----------+---------------------------------------------------------------------------------------+
|
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
.. _wait_v2:
|
.. _wait_v2:
|
||||||
@ -155,8 +154,6 @@ Wait
|
|||||||
| | | **array** - Lists all `Wait Resource`_ s to use, completely |
|
| | | **array** - Lists all `Wait Resource`_ s to use, completely |
|
||||||
| | | overriding the default. Can be set to ``[]`` to disable all |
|
| | | overriding the default. Can be set to ``[]`` to disable all |
|
||||||
| | | resource types. |
|
| | | resource types. |
|
||||||
| | | NOTE: To use the array form with the ArmadaChart CRD, the keyword |
|
|
||||||
| | | must be ``resources_list`` instead of ``resources``. |
|
|
||||||
| | | |
|
| | | |
|
||||||
| | | See also `Wait Resources Examples`_. |
|
| | | See also `Wait Resources Examples`_. |
|
||||||
+-------------+----------+--------------------------------------------------------------------+
|
+-------------+----------+--------------------------------------------------------------------+
|
||||||
|
@ -1,165 +0,0 @@
|
|||||||
|
|
||||||
apiVersion: "apiextensions.k8s.io/v1"
|
|
||||||
kind: "CustomResourceDefinition"
|
|
||||||
metadata:
|
|
||||||
name: "armadacharts.armada.airshipit.org"
|
|
||||||
spec:
|
|
||||||
group: "armada.airshipit.org"
|
|
||||||
versions:
|
|
||||||
- name: v1alpha1
|
|
||||||
served: true
|
|
||||||
storage: true
|
|
||||||
schema:
|
|
||||||
openAPIV3Schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
spec:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
release:
|
|
||||||
type: string
|
|
||||||
namespace:
|
|
||||||
type: string
|
|
||||||
values:
|
|
||||||
type: object
|
|
||||||
x-kubernetes-preserve-unknown-fields: true
|
|
||||||
protected:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
continue_processing:
|
|
||||||
type: boolean
|
|
||||||
test:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
enabled:
|
|
||||||
type: boolean
|
|
||||||
timeout:
|
|
||||||
type: integer
|
|
||||||
options:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
cleanup:
|
|
||||||
type: boolean
|
|
||||||
wait:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
timeout:
|
|
||||||
type: integer
|
|
||||||
resources:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
labels:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
min_ready:
|
|
||||||
x-kubernetes-int-or-string: true
|
|
||||||
anyOf:
|
|
||||||
- type: integer
|
|
||||||
- type: string
|
|
||||||
required:
|
|
||||||
type: boolean
|
|
||||||
resources_list:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
labels:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
min_ready:
|
|
||||||
x-kubernetes-int-or-string: true
|
|
||||||
anyOf:
|
|
||||||
- type: integer
|
|
||||||
- type: string
|
|
||||||
required:
|
|
||||||
type: boolean
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- type
|
|
||||||
labels:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
native:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
enabled:
|
|
||||||
type: boolean
|
|
||||||
# Note: This is specific to the kubernetes schema.
|
|
||||||
# Dynamically typed fields are disallowed by kubernetes
|
|
||||||
# structural schemas, so object and list resource overrides
|
|
||||||
# need two separate fields. We specify here that, exactly one
|
|
||||||
# of these can be given.
|
|
||||||
not:
|
|
||||||
allOf:
|
|
||||||
- required:
|
|
||||||
- resources
|
|
||||||
- required:
|
|
||||||
- resources_list
|
|
||||||
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:
|
|
||||||
pre:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
delete:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
labels:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- type
|
|
||||||
options:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
force:
|
|
||||||
type: boolean
|
|
||||||
recreate_pods:
|
|
||||||
type: boolean
|
|
||||||
no_hooks:
|
|
||||||
type: boolean
|
|
||||||
required:
|
|
||||||
- namespace
|
|
||||||
- release
|
|
||||||
- source
|
|
||||||
scope: "Namespaced"
|
|
||||||
names:
|
|
||||||
plural: "armadacharts"
|
|
||||||
singular: "armadachart"
|
|
||||||
kind: "ArmadaChart"
|
|
@ -1,3 +0,0 @@
|
|||||||
resources:
|
|
||||||
- chart-crd.yaml
|
|
||||||
- rbac.yaml
|
|
@ -1,62 +0,0 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: armada-controller
|
|
||||||
labels:
|
|
||||||
rbac.armada.airshipit.org/aggregate-to-armada: "true"
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- "apps"
|
|
||||||
resources:
|
|
||||||
- deployments
|
|
||||||
- statefulsets
|
|
||||||
- daemonsets
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- batch
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- jobs
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- apiextensions.k8s.io
|
|
||||||
resources:
|
|
||||||
- customresourcedefinitions
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- create
|
|
||||||
- apiGroups:
|
|
||||||
- armada.process
|
|
||||||
resources:
|
|
||||||
- locks
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- patch
|
|
||||||
- update
|
|
||||||
- apiGroups:
|
|
||||||
- armada.airshipit.org
|
|
||||||
resources:
|
|
||||||
- armadacharts
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
---
|
|
@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Copyright 2020 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.
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
CURRENT_DIR="$(pwd)"
|
|
||||||
: "${INSTALL_PATH:="../"}"
|
|
||||||
cd ${INSTALL_PATH}
|
|
||||||
: "${OSH_INFRA_COMMIT:="dc58ef9dddd0326cc86229eda4e21e269adb31be"}"
|
|
||||||
|
|
||||||
# Clone openstack-helm-infra
|
|
||||||
git clone https://opendev.org/openstack/openstack-helm-infra.git
|
|
||||||
cd openstack-helm-infra
|
|
||||||
git checkout "${OSH_INFRA_COMMIT}"
|
|
||||||
|
|
||||||
cd "${CURRENT_DIR}"
|
|
@ -1,45 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright 2019, AT&T Intellectual Property
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
CURRENT_DIR="$(pwd)"
|
|
||||||
: "${OSH_INFRA_PATH:="../openstack-helm-infra"}"
|
|
||||||
|
|
||||||
# Configure proxy settings if $PROXY is set
|
|
||||||
if [ -n "${PROXY}" ]; then
|
|
||||||
. tools/deployment/airskiff/common/setup-proxy.sh
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Deploy K8s with Minikube
|
|
||||||
cd "${OSH_INFRA_PATH}"
|
|
||||||
bash -c "./tools/deployment/common/005-deploy-k8s.sh"
|
|
||||||
|
|
||||||
# Add user to Docker group
|
|
||||||
# NOTE: This requires re-authentication. Restart your shell.
|
|
||||||
sudo adduser "$(whoami)" docker
|
|
||||||
sudo su - "$USER" -c bash <<'END_SCRIPT'
|
|
||||||
if echo $(groups) | grep -qv 'docker'; then
|
|
||||||
echo "You need to logout to apply group permissions"
|
|
||||||
echo "Please logout and login"
|
|
||||||
fi
|
|
||||||
END_SCRIPT
|
|
||||||
|
|
||||||
# clean up /etc/resolv.conf, if it includes a localhost dns address
|
|
||||||
sudo sed -i.bkp '/^nameserver.*127.0.0.1/d
|
|
||||||
w /dev/stdout' /etc/resolv.conf
|
|
||||||
|
|
||||||
cd "${CURRENT_DIR}"
|
|
@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright 2020 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.
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|
||||||
./tools/airship2-integration/test/test.sh basic
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: "armada.airshipit.org/v1alpha1"
|
|
||||||
kind: "ArmadaChart"
|
|
||||||
metadata:
|
|
||||||
name: a1
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
release: a1
|
|
||||||
namespace: test
|
|
||||||
wait:
|
|
||||||
timeout: 100
|
|
||||||
labels:
|
|
||||||
release_group: armada-a1
|
|
||||||
source:
|
|
||||||
location: https://kubernetes-charts-incubator.storage.googleapis.com/raw-0.2.3.tgz
|
|
||||||
subpath: raw
|
|
||||||
type: tar
|
|
||||||
values:
|
|
||||||
resources:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: a1
|
|
||||||
data:
|
|
||||||
chart: a1
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: "armada.airshipit.org/v1alpha1"
|
|
||||||
kind: "ArmadaChart"
|
|
||||||
metadata:
|
|
||||||
name: a2
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
release: a2
|
|
||||||
namespace: test
|
|
||||||
wait:
|
|
||||||
timeout: 100
|
|
||||||
labels:
|
|
||||||
release_group: armada-a1
|
|
||||||
source:
|
|
||||||
location: https://kubernetes-charts-incubator.storage.googleapis.com/raw-0.2.3.tgz
|
|
||||||
subpath: raw
|
|
||||||
type: tar
|
|
||||||
values:
|
|
||||||
resources:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: a2
|
|
||||||
data:
|
|
||||||
chart: a2
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: "armada.airshipit.org/v1alpha1"
|
|
||||||
kind: "ArmadaChart"
|
|
||||||
metadata:
|
|
||||||
name: b1
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
release: b1
|
|
||||||
namespace: test
|
|
||||||
wait:
|
|
||||||
timeout: 100
|
|
||||||
labels:
|
|
||||||
release_group: armada-b1
|
|
||||||
source:
|
|
||||||
location: https://kubernetes-charts-incubator.storage.googleapis.com/raw-0.2.3.tgz
|
|
||||||
subpath: raw
|
|
||||||
type: tar
|
|
||||||
values:
|
|
||||||
resources:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: b1
|
|
||||||
data:
|
|
||||||
chart: b1
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: "armada.airshipit.org/v1alpha1"
|
|
||||||
kind: "ArmadaChart"
|
|
||||||
metadata:
|
|
||||||
name: b2
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
release: b2
|
|
||||||
namespace: test
|
|
||||||
wait:
|
|
||||||
timeout: 100
|
|
||||||
labels:
|
|
||||||
release_group: armada-b2
|
|
||||||
source:
|
|
||||||
location: https://kubernetes-charts-incubator.storage.googleapis.com/raw-0.2.3.tgz
|
|
||||||
subpath: raw
|
|
||||||
type: tar
|
|
||||||
values:
|
|
||||||
resources:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: b2
|
|
||||||
data:
|
|
||||||
chart: b2
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: "armada.airshipit.org/v1alpha1"
|
|
||||||
kind: "ArmadaChart"
|
|
||||||
metadata:
|
|
||||||
name: b3
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
release: b3
|
|
||||||
namespace: test
|
|
||||||
wait:
|
|
||||||
timeout: 100
|
|
||||||
labels:
|
|
||||||
release_group: armada-b3
|
|
||||||
source:
|
|
||||||
location: https://kubernetes-charts-incubator.storage.googleapis.com/raw-0.2.3.tgz
|
|
||||||
subpath: raw
|
|
||||||
type: tar
|
|
||||||
values:
|
|
||||||
resources:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: b3
|
|
||||||
data:
|
|
||||||
chart: b3
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: "armada.airshipit.org/v1alpha1"
|
|
||||||
kind: "ArmadaChart"
|
|
||||||
metadata:
|
|
||||||
name: c1
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
release: c1
|
|
||||||
namespace: test
|
|
||||||
wait:
|
|
||||||
timeout: 100
|
|
||||||
labels:
|
|
||||||
release_group: armada-c1
|
|
||||||
source:
|
|
||||||
location: https://kubernetes-charts-incubator.storage.googleapis.com/raw-0.2.3.tgz
|
|
||||||
subpath: raw
|
|
||||||
type: tar
|
|
||||||
values:
|
|
||||||
resources:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: c1
|
|
||||||
data:
|
|
||||||
chart: c1
|
|
@ -1,51 +0,0 @@
|
|||||||
# Copyright (c) 2020 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.
|
|
||||||
---
|
|
||||||
apiVersion: batch/v1
|
|
||||||
kind: Job
|
|
||||||
metadata:
|
|
||||||
namespace: "${NAMESPACE}"
|
|
||||||
name: "${JOB_NAME}"
|
|
||||||
spec:
|
|
||||||
backoffLimit: 0
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
serviceAccountName: ${SERVICE_ACCOUNT}
|
|
||||||
restartPolicy: Never
|
|
||||||
containers:
|
|
||||||
- name: "test-airship2-integration"
|
|
||||||
image: "${IMAGE}"
|
|
||||||
imagePullPolicy: Never
|
|
||||||
volumeMounts:
|
|
||||||
- name: kube-config
|
|
||||||
mountPath: /armada/.kube/config
|
|
||||||
command:
|
|
||||||
- /bin/bash
|
|
||||||
- -c
|
|
||||||
- |-
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
apply_chart() {
|
|
||||||
NAME=$1
|
|
||||||
armada apply_chart kube:armadacharts/$NAMESPACE/${DOLLAR}NAME --release-prefix ${RELEASE_PREFIX}
|
|
||||||
}
|
|
||||||
|
|
||||||
for CHART in ${CHARTS_SPACE_SEPARATED}; do
|
|
||||||
apply_chart ${DOLLAR}CHART
|
|
||||||
done
|
|
||||||
volumes:
|
|
||||||
- name: kube-config
|
|
||||||
hostPath:
|
|
||||||
path: "${KUBE_CONFIG}"
|
|
||||||
...
|
|
@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: ${NAMESPACE}
|
|
@ -1,18 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: ${SERVICE_ACCOUNT}
|
|
||||||
namespace: ${NAMESPACE}
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: ${SERVICE_ACCOUNT}-armada-controller
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: ${SERVICE_ACCOUNT}
|
|
||||||
namespace: ${NAMESPACE}
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: armada-controller
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
@ -1,61 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright 2020 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.
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
EXAMPLE=$1
|
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|
||||||
|
|
||||||
export NAMESPACE=test
|
|
||||||
export SERVICE_ACCOUNT=test-armada
|
|
||||||
export KUBE_CONFIG=~/.kube/config
|
|
||||||
export RELEASE_PREFIX=test
|
|
||||||
export JOB_NAME=apply-chart-test
|
|
||||||
export IMAGE=quay.io/airshipit/armada:latest-ubuntu_bionic
|
|
||||||
TIMEOUT=300
|
|
||||||
# See https://stackoverflow.com/a/24964089
|
|
||||||
export DOLLAR="\$"
|
|
||||||
|
|
||||||
# Cleanup any previous runs
|
|
||||||
cleanup() {
|
|
||||||
kubectl delete namespace $NAMESPACE --ignore-not-found=true
|
|
||||||
for i in $(helm ls --short | grep $RELEASE_PREFIX-); do helm del --purge $i; done
|
|
||||||
}
|
|
||||||
cleanup
|
|
||||||
|
|
||||||
# Install namespace
|
|
||||||
envsubst < $DIR/test-namespace.yaml | kubectl apply -f -
|
|
||||||
# Install CRD
|
|
||||||
kubectl apply -k ./manifests
|
|
||||||
# Install RBAC
|
|
||||||
envsubst < $DIR/test-rbac.yaml | kubectl apply -f -
|
|
||||||
# Install example CRs
|
|
||||||
kubectl apply -R -f $DIR/examples/$EXAMPLE
|
|
||||||
|
|
||||||
# Run test
|
|
||||||
export CHARTS=$(kubectl get armadacharts -n $NAMESPACE -o name | cut -d / -f2)
|
|
||||||
export CHARTS_SPACE_SEPARATED=$(echo "$CHARTS" | tr "\n" " ")
|
|
||||||
|
|
||||||
envsubst < $DIR/test-job.yaml | kubectl create -f -
|
|
||||||
# Wait for test job completion
|
|
||||||
kubectl wait --timeout ${TIMEOUT}s --for=condition=Complete -n $NAMESPACE job/$JOB_NAME
|
|
||||||
POD_NAME=$(kubectl get pods -n $NAMESPACE -l job-name=$JOB_NAME -o json | jq -r '.items[0].metadata.name')
|
|
||||||
kubectl logs -n $NAMESPACE $POD_NAME
|
|
||||||
|
|
||||||
ACTUAL=$(helm ls --short)
|
|
||||||
EXPECTED=$(echo "$CHARTS" | sed -e "s/^/$RELEASE_PREFIX-/")
|
|
||||||
diff <(echo "$ACTUAL") <(echo "$EXPECTED")
|
|
@ -1,45 +0,0 @@
|
|||||||
# Copyright 2018 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.
|
|
||||||
|
|
||||||
- hosts: primary
|
|
||||||
tasks:
|
|
||||||
- name: Clone Required Repositories
|
|
||||||
shell: |
|
|
||||||
./tools/airship2-integration/000-clone-dependencies.sh
|
|
||||||
args:
|
|
||||||
chdir: "{{ zuul.project.src_dir }}"
|
|
||||||
|
|
||||||
- name: Deploy Kubernetes with Minikube
|
|
||||||
shell: |
|
|
||||||
./tools/airship2-integration/010-deploy-k8s.sh
|
|
||||||
args:
|
|
||||||
chdir: "{{ zuul.project.src_dir }}"
|
|
||||||
|
|
||||||
- name: Build Armada with submitted changes
|
|
||||||
shell: |
|
|
||||||
# Add image to minikube
|
|
||||||
eval $(minikube docker-env)
|
|
||||||
make images
|
|
||||||
args:
|
|
||||||
chdir: "{{ zuul.project.src_dir }}"
|
|
||||||
become: yes
|
|
||||||
|
|
||||||
- name: Apply charts
|
|
||||||
shell: |
|
|
||||||
mkdir ~/.kube
|
|
||||||
cp -rp /home/zuul/.kube/config ~/.kube/config
|
|
||||||
./tools/airship2-integration/020-apply-charts.sh
|
|
||||||
args:
|
|
||||||
chdir: "{{ zuul.project.src_dir }}"
|
|
||||||
become: yes
|
|
Loading…
Reference in New Issue
Block a user