Merge "Airship 2 support features"
This commit is contained in:
commit
d33a92e278
21
.zuul.yaml
21
.zuul.yaml
@ -28,6 +28,7 @@
|
||||
- armada-docker-build-gate-ubuntu_xenial
|
||||
- armada-docker-build-gate-opensuse
|
||||
- armada-airskiff-deploy
|
||||
- armada-airship2-integration
|
||||
gate:
|
||||
jobs:
|
||||
- openstack-tox-pep8
|
||||
@ -126,6 +127,26 @@
|
||||
- ^releasenotes/.*$
|
||||
- ^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:
|
||||
name: armada-docker-publish-ubuntu_bionic
|
||||
timeout: 1800
|
||||
|
207
armada/cli/apply_chart.py
Normal file
207
armada/cli/apply_chart.py
Normal file
@ -0,0 +1,207 @@
|
||||
# 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()
|
@ -21,15 +21,14 @@ from armada import const
|
||||
from armada.conf import set_current_chart
|
||||
from armada.exceptions import armada_exceptions
|
||||
from armada.exceptions import override_exceptions
|
||||
from armada.exceptions import source_exceptions
|
||||
from armada.exceptions import tiller_exceptions
|
||||
from armada.exceptions import validate_exceptions
|
||||
from armada.handlers import metrics
|
||||
from armada.handlers.chart_deploy import ChartDeploy
|
||||
from armada.handlers.chart_download import ChartDownload
|
||||
from armada.handlers.manifest import Manifest
|
||||
from armada.handlers.override import Override
|
||||
from armada.utils.release import release_prefixer
|
||||
from armada.utils import source
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
@ -88,7 +87,7 @@ class Armada(object):
|
||||
raise
|
||||
self.manifest = Manifest(
|
||||
self.documents, target_manifest=target_manifest).get_manifest()
|
||||
self.chart_cache = {}
|
||||
self.chart_download = ChartDownload()
|
||||
self.chart_deploy = ChartDeploy(
|
||||
self.manifest, disable_update_pre, disable_update_post,
|
||||
k8s_wait_attempts, k8s_wait_attempt_sleep, timeout, self.tiller)
|
||||
@ -108,71 +107,7 @@ class Armada(object):
|
||||
for group in manifest_data.get(const.KEYWORD_GROUPS, []):
|
||||
for ch in group.get(const.KEYWORD_DATA).get(const.KEYWORD_CHARTS,
|
||||
[]):
|
||||
self.get_chart(ch)
|
||||
|
||||
def get_chart(self, ch):
|
||||
manifest_name = self.manifest['metadata']['name']
|
||||
chart_name = ch['metadata']['name']
|
||||
with metrics.CHART_DOWNLOAD.get_context(manifest_name, chart_name):
|
||||
return self._get_chart(ch)
|
||||
|
||||
def _get_chart(self, ch):
|
||||
chart = ch.get(const.KEYWORD_DATA)
|
||||
chart_source = chart.get('source', {})
|
||||
location = chart_source.get('location')
|
||||
ct_type = chart_source.get('type')
|
||||
subpath = chart_source.get('subpath', '.')
|
||||
proxy_server = chart_source.get('proxy_server')
|
||||
|
||||
if ct_type == 'local':
|
||||
chart['source_dir'] = (location, subpath)
|
||||
elif ct_type == 'tar':
|
||||
source_key = (ct_type, location)
|
||||
|
||||
if source_key not in self.chart_cache:
|
||||
LOG.info(
|
||||
"Downloading tarball from: %s / proxy %s", location,
|
||||
proxy_server or "not set")
|
||||
|
||||
if not CONF.certs:
|
||||
LOG.warn(
|
||||
'Disabling server validation certs to extract charts')
|
||||
tarball_dir = source.get_tarball(
|
||||
location, verify=False, proxy_server=proxy_server)
|
||||
else:
|
||||
tarball_dir = source.get_tarball(
|
||||
location, verify=CONF.certs, proxy_server=proxy_server)
|
||||
self.chart_cache[source_key] = tarball_dir
|
||||
chart['source_dir'] = (self.chart_cache.get(source_key), subpath)
|
||||
elif ct_type == 'git':
|
||||
reference = chart_source.get('reference', 'master')
|
||||
source_key = (ct_type, location, reference)
|
||||
|
||||
if source_key not in self.chart_cache:
|
||||
auth_method = chart_source.get('auth_method')
|
||||
|
||||
logstr = 'Cloning repo: {} from branch: {}'.format(
|
||||
location, reference)
|
||||
if proxy_server:
|
||||
logstr += ' proxy: {}'.format(proxy_server)
|
||||
if auth_method:
|
||||
logstr += ' auth method: {}'.format(auth_method)
|
||||
LOG.info(logstr)
|
||||
|
||||
repo_dir = source.git_clone(
|
||||
location,
|
||||
reference,
|
||||
proxy_server=proxy_server,
|
||||
auth_method=auth_method)
|
||||
|
||||
self.chart_cache[source_key] = repo_dir
|
||||
chart['source_dir'] = (self.chart_cache.get(source_key), subpath)
|
||||
else:
|
||||
name = ch['metadata']['name']
|
||||
raise source_exceptions.ChartSourceException(ct_type, name)
|
||||
|
||||
for dep in ch.get(const.KEYWORD_DATA, {}).get('dependencies', []):
|
||||
self.get_chart(dep)
|
||||
self.chart_download.get_chart(ch, manifest=self.manifest)
|
||||
|
||||
def sync(self):
|
||||
'''
|
||||
@ -285,10 +220,7 @@ class Armada(object):
|
||||
'''
|
||||
LOG.info("Performing post-flight operations.")
|
||||
|
||||
# Delete temp dirs used for deployment
|
||||
for chart_dir in self.chart_cache.values():
|
||||
LOG.debug('Removing temp chart directory: %s', chart_dir)
|
||||
source.source_cleanup(chart_dir)
|
||||
self.chart_download.cleanup()
|
||||
|
||||
def _chart_cleanup(self, prefix, chart_groups, msg):
|
||||
LOG.info('Processing chart cleanup to remove unspecified releases.')
|
||||
|
@ -47,14 +47,16 @@ class ChartDeploy(object):
|
||||
def execute(
|
||||
self, ch, cg_test_all_charts, prefix, known_releases, concurrency):
|
||||
chart_name = ch['metadata']['name']
|
||||
manifest_name = self.manifest['metadata']['name']
|
||||
manifest_name = self.manifest['metadata'][
|
||||
'name'] if self.manifest else ''
|
||||
with metrics.CHART_HANDLE.get_context(concurrency, manifest_name,
|
||||
chart_name):
|
||||
return self._execute(
|
||||
ch, cg_test_all_charts, prefix, known_releases)
|
||||
|
||||
def _execute(self, ch, cg_test_all_charts, prefix, known_releases):
|
||||
manifest_name = self.manifest['metadata']['name']
|
||||
manifest_name = self.manifest['metadata'][
|
||||
'name'] if self.manifest else ''
|
||||
chart = ch[const.KEYWORD_DATA]
|
||||
chart_name = ch['metadata']['name']
|
||||
namespace = chart.get('namespace')
|
||||
|
104
armada/handlers/chart_download.py
Normal file
104
armada/handlers/chart_download.py
Normal file
@ -0,0 +1,104 @@
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from armada import const
|
||||
from armada.exceptions import source_exceptions
|
||||
from armada.handlers import metrics
|
||||
from armada.utils import source
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class ChartDownload():
|
||||
def __init__(self):
|
||||
self.chart_cache = {}
|
||||
|
||||
def get_chart(self, ch, manifest=None):
|
||||
manifest_name = manifest['metadata']['name'] if manifest else None
|
||||
chart_name = ch['metadata']['name']
|
||||
with metrics.CHART_DOWNLOAD.get_context(manifest_name, chart_name):
|
||||
return self._get_chart(ch, manifest)
|
||||
|
||||
def _get_chart(self, ch, manifest):
|
||||
chart = ch.get(const.KEYWORD_DATA)
|
||||
chart_source = chart.get('source', {})
|
||||
location = chart_source.get('location')
|
||||
ct_type = chart_source.get('type')
|
||||
subpath = chart_source.get('subpath', '.')
|
||||
proxy_server = chart_source.get('proxy_server')
|
||||
|
||||
if ct_type == 'local':
|
||||
chart['source_dir'] = (location, subpath)
|
||||
elif ct_type == 'tar':
|
||||
source_key = (ct_type, location)
|
||||
|
||||
if source_key not in self.chart_cache:
|
||||
LOG.info(
|
||||
"Downloading tarball from: %s / proxy %s", location,
|
||||
proxy_server or "not set")
|
||||
|
||||
if not CONF.certs:
|
||||
LOG.warn(
|
||||
'Disabling server validation certs to extract charts')
|
||||
tarball_dir = source.get_tarball(
|
||||
location, verify=False, proxy_server=proxy_server)
|
||||
else:
|
||||
tarball_dir = source.get_tarball(
|
||||
location, verify=CONF.certs, proxy_server=proxy_server)
|
||||
self.chart_cache[source_key] = tarball_dir
|
||||
chart['source_dir'] = (self.chart_cache.get(source_key), subpath)
|
||||
elif ct_type == 'git':
|
||||
reference = chart_source.get('reference', 'master')
|
||||
source_key = (ct_type, location, reference)
|
||||
|
||||
if source_key not in self.chart_cache:
|
||||
auth_method = chart_source.get('auth_method')
|
||||
|
||||
logstr = 'Cloning repo: {} from branch: {}'.format(
|
||||
location, reference)
|
||||
if proxy_server:
|
||||
logstr += ' proxy: {}'.format(proxy_server)
|
||||
if auth_method:
|
||||
logstr += ' auth method: {}'.format(auth_method)
|
||||
LOG.info(logstr)
|
||||
|
||||
repo_dir = source.git_clone(
|
||||
location,
|
||||
reference,
|
||||
proxy_server=proxy_server,
|
||||
auth_method=auth_method)
|
||||
|
||||
self.chart_cache[source_key] = repo_dir
|
||||
chart['source_dir'] = (self.chart_cache.get(source_key), subpath)
|
||||
else:
|
||||
name = ch['metadata']['name']
|
||||
raise source_exceptions.ChartSourceException(ct_type, name)
|
||||
|
||||
for dep in ch.get(const.KEYWORD_DATA, {}).get('dependencies', []):
|
||||
self.get_chart(dep, manifest=manifest)
|
||||
|
||||
def cleanup(self):
|
||||
'''
|
||||
Operations to run after deployment process has terminated
|
||||
'''
|
||||
LOG.info("Performing post-flight operations.")
|
||||
|
||||
# Delete temp dirs used for deployment
|
||||
for chart_dir in self.chart_cache.values():
|
||||
LOG.debug('Removing temp chart directory: %s', chart_dir)
|
||||
source.source_cleanup(chart_dir)
|
@ -17,8 +17,10 @@
|
||||
import urllib.parse
|
||||
import re
|
||||
|
||||
import requests
|
||||
from oslo_log import log as logging
|
||||
import requests
|
||||
import yaml
|
||||
from kubernetes.client.rest import ApiException
|
||||
|
||||
from armada.exceptions.source_exceptions import InvalidPathException
|
||||
from armada.utils import keystone as ks_utils
|
||||
@ -30,7 +32,7 @@ class ReferenceResolver(object):
|
||||
"""Class for handling different data references to resolve the data."""
|
||||
|
||||
@classmethod
|
||||
def resolve_reference(cls, design_ref):
|
||||
def resolve_reference(cls, design_ref, k8s=None):
|
||||
"""Resolve a reference to a design document.
|
||||
|
||||
Locate a schema handler based on the URI scheme of the data reference
|
||||
@ -51,10 +53,16 @@ class ReferenceResolver(object):
|
||||
|
||||
# when scheme is a empty string assume it is a local
|
||||
# file path
|
||||
if design_uri.scheme == '':
|
||||
handler = cls.scheme_handlers.get('file')
|
||||
else:
|
||||
handler = cls.scheme_handlers.get(design_uri.scheme, None)
|
||||
scheme = design_uri.scheme or 'file'
|
||||
handler = cls.scheme_handlers.get(scheme, None)
|
||||
handler = handler.__get__(None, cls)
|
||||
if design_uri.scheme == 'kube':
|
||||
handler_2 = handler
|
||||
|
||||
def handler_1(design_uri):
|
||||
return handler_2(design_uri, k8s)
|
||||
|
||||
handler = handler_1
|
||||
|
||||
if handler is None:
|
||||
raise InvalidPathException(
|
||||
@ -71,6 +79,50 @@ class ReferenceResolver(object):
|
||||
|
||||
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
|
||||
def resolve_reference_http(cls, design_uri):
|
||||
"""Retrieve design documents from http/https endpoints.
|
||||
@ -134,6 +186,7 @@ class ReferenceResolver(object):
|
||||
return resp.content
|
||||
|
||||
scheme_handlers = {
|
||||
'kube': resolve_reference_kube,
|
||||
'http': resolve_reference_http,
|
||||
'file': resolve_reference_file,
|
||||
'https': resolve_reference_http,
|
||||
|
@ -22,56 +22,12 @@ from armada.handlers import schema
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Manifest(object):
|
||||
def __init__(self, documents, target_manifest=None):
|
||||
"""Instantiates a Manifest object.
|
||||
|
||||
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.
|
||||
"""
|
||||
class Doc(object):
|
||||
def __init__(self, documents):
|
||||
self.documents = deepcopy(documents)
|
||||
self.charts, self.groups, manifests = self._find_documents(
|
||||
target_manifest)
|
||||
self.charts, self.groups, self.manifests = self._find_documents()
|
||||
|
||||
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):
|
||||
def _find_documents(self):
|
||||
"""Returns the chart documents, chart group documents,
|
||||
and Armada manifest
|
||||
|
||||
@ -97,14 +53,44 @@ class Manifest(object):
|
||||
if schema_info.type == schema.TYPE_CHARTGROUP:
|
||||
groups.append(document)
|
||||
if schema_info.type == schema.TYPE_MANIFEST:
|
||||
manifest_name = document.get('metadata', {}).get('name')
|
||||
if target_manifest:
|
||||
if manifest_name == target_manifest:
|
||||
manifests.append(document)
|
||||
else:
|
||||
manifests.append(document)
|
||||
manifests.append(document)
|
||||
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):
|
||||
"""Returns a chart document with the specified name
|
||||
|
||||
@ -121,22 +107,6 @@ class Manifest(object):
|
||||
details='Could not find {} named "{}"'.format(
|
||||
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):
|
||||
"""Recursively build chart dependencies for ``chart``.
|
||||
|
||||
@ -164,6 +134,90 @@ class Manifest(object):
|
||||
else:
|
||||
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):
|
||||
"""Builds the chart dependencies for`charts`chart group``.
|
||||
|
||||
|
@ -59,6 +59,9 @@ class ChartWait():
|
||||
schema_info = get_schema_info(self.chart['schema'])
|
||||
|
||||
resources = self.wait_config.get('resources')
|
||||
if not resources:
|
||||
resources = self.wait_config.get('resources_list')
|
||||
|
||||
if isinstance(resources, list):
|
||||
# Explicit resource config list provided.
|
||||
resources_list = resources
|
||||
|
@ -19,6 +19,7 @@ from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
|
||||
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.rollback import rollback_charts
|
||||
from armada.cli.test import test_charts
|
||||
@ -49,6 +50,7 @@ def main(ctx, debug, api, url, token):
|
||||
|
||||
\b
|
||||
$ armada apply
|
||||
$ armada apply_chart
|
||||
$ armada delete
|
||||
$ armada rollback
|
||||
$ armada test
|
||||
@ -88,6 +90,7 @@ def main(ctx, debug, api, url, token):
|
||||
|
||||
|
||||
main.add_command(apply_create)
|
||||
main.add_command(apply_chart)
|
||||
main.add_command(delete_charts)
|
||||
main.add_command(rollback_charts)
|
||||
main.add_command(test_charts)
|
||||
|
@ -143,16 +143,21 @@ data:
|
||||
enabled: true
|
||||
"""
|
||||
|
||||
CHART_SOURCES = [
|
||||
('git://opendev.org/dummy/armada.git', 'chart_1'),
|
||||
('/tmp/dummy/armada', 'chart_2'), ('/tmp/dummy/armada', 'chart_3'),
|
||||
('/tmp/dummy/armada', 'chart_4')
|
||||
]
|
||||
CHART_SOURCES = (
|
||||
('git://opendev.org/dummy/armada.git',
|
||||
'chart_1'), ('/tmp/dummy/armada', 'chart_2'),
|
||||
('/tmp/dummy/armada', 'chart_3'), ('/tmp/dummy/armada', 'chart_4'))
|
||||
|
||||
|
||||
# TODO(seaneagan): Add unit tests with dependencies, including transitive.
|
||||
class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||
def _test_pre_flight_ops(self, armada_obj):
|
||||
def _test_pre_flight_ops(self, armada_obj, MockChartDownload):
|
||||
def set_source_dir(ch, manifest=None):
|
||||
d = ch['data']
|
||||
d['source_dir'] = (d['source']['location'], d['source']['subpath'])
|
||||
|
||||
MockChartDownload.return_value.get_chart.side_effect = set_source_dir
|
||||
|
||||
armada_obj.pre_flight_ops()
|
||||
|
||||
expected_config = {
|
||||
@ -305,38 +310,30 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||
self.assertIn('data', armada_obj.manifest)
|
||||
self.assertEqual(expected_config, armada_obj.manifest)
|
||||
|
||||
@mock.patch.object(armada, 'source')
|
||||
def test_pre_flight_ops(self, mock_source):
|
||||
@mock.patch.object(armada, 'ChartDownload')
|
||||
def test_pre_flight_ops(self, MockChartDownload):
|
||||
"""Test pre-flight checks and operations."""
|
||||
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
||||
m_tiller = mock.Mock()
|
||||
m_tiller.tiller_status.return_value = True
|
||||
armada_obj = armada.Armada(yaml_documents, m_tiller)
|
||||
|
||||
# Mock methods called by `pre_flight_ops()`.
|
||||
mock_source.git_clone.return_value = CHART_SOURCES[0][0]
|
||||
self._test_pre_flight_ops(armada_obj, MockChartDownload)
|
||||
|
||||
self._test_pre_flight_ops(armada_obj)
|
||||
MockChartDownload.return_value.get_chart.assert_called()
|
||||
|
||||
mock_source.git_clone.assert_called_once_with(
|
||||
'git://opendev.org/dummy/armada.git',
|
||||
'master',
|
||||
auth_method=None,
|
||||
proxy_server=None)
|
||||
|
||||
@mock.patch.object(armada, 'source')
|
||||
def test_post_flight_ops(self, mock_source):
|
||||
@mock.patch.object(armada, 'ChartDownload')
|
||||
def test_post_flight_ops(self, MockChartDownload):
|
||||
"""Test post-flight operations."""
|
||||
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
||||
|
||||
# Mock methods called by `pre_flight_ops()`.
|
||||
m_tiller = mock.Mock()
|
||||
m_tiller.tiller_status.return_value = True
|
||||
mock_source.git_clone.return_value = CHART_SOURCES[0][0]
|
||||
|
||||
armada_obj = armada.Armada(yaml_documents, m_tiller)
|
||||
|
||||
self._test_pre_flight_ops(armada_obj)
|
||||
self._test_pre_flight_ops(armada_obj, MockChartDownload)
|
||||
|
||||
armada_obj.post_flight_ops()
|
||||
|
||||
@ -345,8 +342,7 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||
const.KEYWORD_CHARTS)):
|
||||
if chart.get(
|
||||
const.KEYWORD_DATA).get('source').get('type') == 'git':
|
||||
mock_source.source_cleanup.assert_called_with(
|
||||
CHART_SOURCES[counter][0])
|
||||
MockChartDownload.return_value.cleanup.assert_called_with()
|
||||
|
||||
# TODO(seaneagan): Separate ChartDeploy tests into separate module.
|
||||
# TODO(seaneagan): Once able to make mock library sufficiently thread safe,
|
||||
@ -671,19 +667,17 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
|
||||
|
||||
|
||||
class ArmadaNegativeHandlerTestCase(base.ArmadaTestCase):
|
||||
@mock.patch.object(armada, 'source')
|
||||
def test_armada_get_manifest_exception(self, mock_source):
|
||||
@mock.patch.object(armada, 'ChartDownload')
|
||||
def test_armada_get_manifest_exception(self, MockChartDownload):
|
||||
"""Test armada handling with invalid manifest."""
|
||||
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
||||
error_re = (
|
||||
'.*Documents must include at least one of each of .* and '
|
||||
'only one .*')
|
||||
error_re = ('.*Documents must include at least one of each of .*')
|
||||
self.assertRaisesRegexp(
|
||||
ManifestException, error_re, armada.Armada, yaml_documents[:1],
|
||||
mock.MagicMock())
|
||||
|
||||
@mock.patch.object(armada, 'source')
|
||||
def test_armada_override_exception(self, mock_source):
|
||||
@mock.patch.object(armada, 'ChartDownload')
|
||||
def test_armada_override_exception(self, MockChartDownload):
|
||||
"""Test Armada checks with invalid chart override."""
|
||||
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
||||
override = ('chart:example-chart-2:name=' 'overridden', )
|
||||
@ -692,8 +686,8 @@ class ArmadaNegativeHandlerTestCase(base.ArmadaTestCase):
|
||||
with self.assertRaisesRegexp(InvalidOverrideValueException, error_re):
|
||||
armada.Armada(yaml_documents, mock.MagicMock(), set_ovr=override)
|
||||
|
||||
@mock.patch.object(armada, 'source')
|
||||
def test_armada_manifest_exception_override_none(self, mock_source):
|
||||
@mock.patch.object(armada, 'ChartDownload')
|
||||
def test_armada_manifest_exception_override_none(self, MockChartDownload):
|
||||
"""Test Armada checks with invalid manifest."""
|
||||
yaml_documents = list(yaml.safe_load_all(TEST_YAML))
|
||||
example_document = [
|
||||
|
@ -15,7 +15,7 @@
|
||||
import copy
|
||||
import os
|
||||
|
||||
import testtools
|
||||
import testtools
|
||||
import yaml
|
||||
|
||||
from armada import exceptions
|
||||
@ -117,7 +117,7 @@ class ManifestTestCase(testtools.TestCase):
|
||||
def test_find_documents(self):
|
||||
armada_manifest = manifest.Manifest(self.documents)
|
||||
chart_documents, chart_groups, manifests = armada_manifest. \
|
||||
_find_documents(target_manifest='armada-manifest')
|
||||
_find_documents()
|
||||
|
||||
# checking if all the chart documents are present
|
||||
self.assertIsInstance(chart_documents, list)
|
||||
@ -344,7 +344,8 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
||||
documents = copy.deepcopy(self.documents)
|
||||
documents.append(documents[-1]) # Copy the last manifest.
|
||||
|
||||
error_re = r'Multiple manifests are not supported.*'
|
||||
error_re = r'Multiple {} documents are not supported.*'.format(
|
||||
schema.TYPE_MANIFEST)
|
||||
self.assertRaisesRegexp(
|
||||
exceptions.ManifestException, error_re, manifest.Manifest,
|
||||
documents)
|
||||
@ -355,7 +356,8 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
||||
documents = copy.deepcopy(self.documents)
|
||||
documents.append(documents[-1]) # Copy the last manifest.
|
||||
|
||||
error_re = r'Multiple manifests are not supported.*'
|
||||
error_re = r'Multiple {} documents are not supported.*'.format(
|
||||
schema.TYPE_MANIFEST)
|
||||
self.assertRaisesRegexp(
|
||||
exceptions.ManifestException,
|
||||
error_re,
|
||||
@ -364,9 +366,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
||||
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 .*')
|
||||
error_re = ('.*Documents must include at least one of each of .*')
|
||||
self.assertRaisesRegexp(
|
||||
exceptions.ManifestException, error_re, manifest.Manifest,
|
||||
documents)
|
||||
@ -374,7 +374,11 @@ class ManifestNegativeTestCase(testtools.TestCase):
|
||||
def test_get_documents_missing_manifest(self):
|
||||
# Validates exceptions.ManifestException is thrown if no manifest is
|
||||
# found. Manifest is last document in sample YAML.
|
||||
self._assert_missing_documents_raises(self.documents[:-1])
|
||||
error_re = 'Documents must include at least one {}'.format(
|
||||
schema.TYPE_MANIFEST)
|
||||
self.assertRaisesRegexp(
|
||||
exceptions.ManifestException, error_re, manifest.Manifest,
|
||||
self.documents[:-1])
|
||||
|
||||
def test_get_documents_missing_charts(self):
|
||||
# Validates exceptions.ManifestException is thrown if no chart is
|
||||
|
53
doc/source/commands/apply_chart.rst
Normal file
53
doc/source/commands/apply_chart.rst
Normal file
@ -0,0 +1,53 @@
|
||||
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,6 +11,7 @@ Commands Guide
|
||||
:caption: Contents:
|
||||
|
||||
apply.rst
|
||||
apply_chart.rst
|
||||
rollback.rst
|
||||
test.rst
|
||||
tiller.rst
|
||||
|
@ -124,6 +124,7 @@ Chart
|
||||
| dependencies | object | (optional) Override the `builtin chart dependencies`_ with a list of Chart documents |
|
||||
| | | to use as dependencies instead. |
|
||||
| | | NOTE: Builtin ".tgz" dependencies are not yet supported. |
|
||||
| | | NOTE: This field is not supported in the ArmadaChart CRD. |
|
||||
+-----------------+----------+---------------------------------------------------------------------------------------+
|
||||
|
||||
.. _wait_v2:
|
||||
@ -154,6 +155,8 @@ Wait
|
||||
| | | **array** - Lists all `Wait Resource`_ s to use, completely |
|
||||
| | | overriding the default. Can be set to ``[]`` to disable all |
|
||||
| | | 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`_. |
|
||||
+-------------+----------+--------------------------------------------------------------------+
|
||||
|
165
manifests/chart-crd.yaml
Normal file
165
manifests/chart-crd.yaml
Normal file
@ -0,0 +1,165 @@
|
||||
|
||||
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"
|
3
manifests/kustomization.yaml
Normal file
3
manifests/kustomization.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
resources:
|
||||
- chart-crd.yaml
|
||||
- rbac.yaml
|
62
manifests/rbac.yaml
Normal file
62
manifests/rbac.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
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
|
||||
---
|
28
tools/airship2-integration/000-clone-dependencies.sh
Executable file
28
tools/airship2-integration/000-clone-dependencies.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/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:="eacf93722136636dcfbd2b68c59b71f071ffc085"}"
|
||||
|
||||
# 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}"
|
45
tools/airship2-integration/010-deploy-k8s.sh
Executable file
45
tools/airship2-integration/010-deploy-k8s.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/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}"
|
20
tools/airship2-integration/020-apply-charts.sh
Executable file
20
tools/airship2-integration/020-apply-charts.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/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
|
24
tools/airship2-integration/test/examples/basic/a1.yaml
Normal file
24
tools/airship2-integration/test/examples/basic/a1.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
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
|
24
tools/airship2-integration/test/examples/basic/a2.yaml
Normal file
24
tools/airship2-integration/test/examples/basic/a2.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
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
|
24
tools/airship2-integration/test/examples/basic/b1.yaml
Normal file
24
tools/airship2-integration/test/examples/basic/b1.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
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
|
24
tools/airship2-integration/test/examples/basic/b2.yaml
Normal file
24
tools/airship2-integration/test/examples/basic/b2.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
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
|
24
tools/airship2-integration/test/examples/basic/b3.yaml
Normal file
24
tools/airship2-integration/test/examples/basic/b3.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
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
|
24
tools/airship2-integration/test/examples/basic/c1.yaml
Normal file
24
tools/airship2-integration/test/examples/basic/c1.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
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
|
51
tools/airship2-integration/test/test-job.yaml
Normal file
51
tools/airship2-integration/test/test-job.yaml
Normal file
@ -0,0 +1,51 @@
|
||||
# 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}"
|
||||
...
|
4
tools/airship2-integration/test/test-namespace.yaml
Normal file
4
tools/airship2-integration/test/test-namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ${NAMESPACE}
|
18
tools/airship2-integration/test/test-rbac.yaml
Normal file
18
tools/airship2-integration/test/test-rbac.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
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
|
61
tools/airship2-integration/test/test.sh
Executable file
61
tools/airship2-integration/test/test.sh
Executable file
@ -0,0 +1,61 @@
|
||||
#!/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")
|
45
tools/gate/playbooks/airship2-integration.yaml
Normal file
45
tools/gate/playbooks/airship2-integration.yaml
Normal file
@ -0,0 +1,45 @@
|
||||
# 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