[DNM] Operator test
Signed-off-by: Ruslan Aliev <raliev@mirantis.com> Change-Id: I76fb41062d152bf360a85d781c19ab5b204769b8
This commit is contained in:
parent
5df69442b0
commit
629051b7a6
|
@ -19,6 +19,13 @@ KEYWORD_GROUPS = 'chart_groups'
|
|||
KEYWORD_CHARTS = 'chart_group'
|
||||
KEYWORD_RELEASE = 'release'
|
||||
|
||||
CHART_VERSION = 'v1'
|
||||
CHART_APIVERSION = 'armada.airshipit.io/v1'
|
||||
CHART_GROUP = 'armada.airshipit.io'
|
||||
CHART_KIND = 'ArmadaChart'
|
||||
CHART_PLURAL = 'armadacharts'
|
||||
CHART_LABEL = 'armada.airshipit.io/release-name'
|
||||
|
||||
# Armada
|
||||
DEFAULT_CHART_TIMEOUT = 900
|
||||
DEFAULT_TEST_TIMEOUT = 300
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
import yaml
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
@ -29,6 +30,7 @@ from armada.handlers.helm import HelmReleaseId
|
|||
from armada.handlers.manifest import Manifest
|
||||
from armada.handlers.override import Override
|
||||
from armada.utils.release import release_prefixer
|
||||
from kubernetes.client.rest import ApiException
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
@ -96,12 +98,37 @@ class Armada(object):
|
|||
"""
|
||||
LOG.info("Performing pre-flight operations.")
|
||||
|
||||
# Clone the chart sources
|
||||
try:
|
||||
self.helm.k8s.read_custom_resource_definition(
|
||||
"armadacharts.armada.airshipit.io")
|
||||
except ApiException as err:
|
||||
if err.status == 404:
|
||||
LOG.info(
|
||||
"ArmadaCharts Custom Resource Definition not found, "
|
||||
"creating now")
|
||||
with open("armadacharts_crd.yaml") as crd_file:
|
||||
body = yaml.load(crd_file, Loader=yaml.CSafeLoader)
|
||||
self.helm.k8s.create_custom_resource_definition(body)
|
||||
else:
|
||||
raise
|
||||
|
||||
# Create namespaces if not exist
|
||||
manifest_data = self.manifest.get(const.KEYWORD_DATA, {})
|
||||
for group in manifest_data.get(const.KEYWORD_GROUPS, []):
|
||||
for ch in group.get(const.KEYWORD_DATA).get(const.KEYWORD_CHARTS,
|
||||
[]):
|
||||
self.chart_download.get_chart(ch, manifest=self.manifest)
|
||||
chart = ch.get(const.KEYWORD_DATA)
|
||||
ns = chart.get('namespace', '')
|
||||
if ns != "":
|
||||
try:
|
||||
self.helm.k8s.read_namespace(ns)
|
||||
except ApiException as err:
|
||||
if err.status == 404:
|
||||
LOG.info(
|
||||
"Unable to find namespace '%s', creating...")
|
||||
self.helm.k8s.create_namespace(ns)
|
||||
else:
|
||||
raise
|
||||
|
||||
def sync(self):
|
||||
'''
|
||||
|
@ -195,8 +222,6 @@ class Armada(object):
|
|||
# End of Charts in ChartGroup
|
||||
LOG.info('All Charts applied in ChartGroup %s.', cg_name)
|
||||
|
||||
self.post_flight_ops()
|
||||
|
||||
if self.enable_chart_cleanup:
|
||||
self._chart_cleanup(
|
||||
prefix,
|
||||
|
@ -205,14 +230,6 @@ class Armada(object):
|
|||
LOG.info('Done applying manifest.')
|
||||
return msg
|
||||
|
||||
def post_flight_ops(self):
|
||||
'''
|
||||
Operations to run after deployment process has terminated
|
||||
'''
|
||||
LOG.info("Performing post-flight operations.")
|
||||
|
||||
self.chart_download.cleanup()
|
||||
|
||||
def _chart_cleanup(self, prefix, chart_groups, msg):
|
||||
LOG.info('Processing chart cleanup to remove unspecified releases.')
|
||||
|
||||
|
|
|
@ -12,22 +12,17 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from kubernetes.client.rest import ApiException
|
||||
from oslo_log import log as logging
|
||||
|
||||
from armada import const
|
||||
from armada.exceptions import armada_exceptions
|
||||
from armada.handlers import metrics
|
||||
from armada.handlers.chartbuilder import ChartBuilder
|
||||
from armada.handlers import helm
|
||||
from armada.handlers.release_diff import ReleaseDiff
|
||||
from armada.handlers.chart_delete import ChartDelete
|
||||
from armada.handlers.pre_update_actions import PreUpdateActions
|
||||
from armada.handlers.schema import get_schema_info
|
||||
from armada.handlers.test import Test
|
||||
from armada.handlers.wait import ChartWait
|
||||
import armada.utils.release as r
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -43,7 +38,7 @@ class ChartDeploy(object):
|
|||
self.k8s_wait_attempts = k8s_wait_attempts
|
||||
self.k8s_wait_attempt_sleep = k8s_wait_attempt_sleep
|
||||
self.timeout = timeout
|
||||
self.helm = helm
|
||||
self.k8s = helm.k8s
|
||||
|
||||
def execute(self, ch, cg_test_all_charts, prefix, concurrency):
|
||||
chart_name = ch['metadata']['name']
|
||||
|
@ -60,25 +55,13 @@ class ChartDeploy(object):
|
|||
release = chart.get('release')
|
||||
release_name = r.release_prefixer(prefix, release)
|
||||
release_id = helm.HelmReleaseId(namespace, release_name)
|
||||
source_dir = chart['source_dir']
|
||||
source_directory = os.path.join(*source_dir)
|
||||
LOG.info('Processing Chart, release=%s', release_id)
|
||||
|
||||
result = {}
|
||||
|
||||
chart_wait = ChartWait(
|
||||
self.helm.k8s,
|
||||
release_id,
|
||||
ch,
|
||||
k8s_wait_attempts=self.k8s_wait_attempts,
|
||||
k8s_wait_attempt_sleep=self.k8s_wait_attempt_sleep,
|
||||
timeout=self.timeout)
|
||||
wait_timeout = chart_wait.get_timeout()
|
||||
|
||||
wait_timeout = self._get_timeout(ch)
|
||||
# Begin Chart timeout deadline
|
||||
deadline = time.time() + wait_timeout
|
||||
old_release = self.helm.release_metadata(release_id)
|
||||
action = metrics.ChartDeployAction.NOOP
|
||||
|
||||
def noop():
|
||||
pass
|
||||
|
@ -87,150 +70,78 @@ class ChartDeploy(object):
|
|||
|
||||
# Resolve action
|
||||
values = chart.get('values', {})
|
||||
pre_actions = {}
|
||||
self._convert_min_ready(chart)
|
||||
|
||||
status = None
|
||||
if old_release:
|
||||
status = r.get_release_status(old_release)
|
||||
|
||||
native_wait_enabled = chart_wait.is_native_enabled()
|
||||
|
||||
chartbuilder = ChartBuilder.from_chart_doc(ch, self.helm)
|
||||
|
||||
if status == helm.STATUS_DEPLOYED:
|
||||
try:
|
||||
self.k8s.read_custom_resource(
|
||||
group=const.CHART_GROUP,
|
||||
version=const.CHART_VERSION,
|
||||
namespace=namespace,
|
||||
plural=const.CHART_PLURAL,
|
||||
name=release_name)
|
||||
|
||||
# indicate to the end user what path we are taking
|
||||
LOG.info("Existing release %s found", release_id)
|
||||
LOG.info("Existing release %s found", release_name)
|
||||
|
||||
# extract the installed chart and installed values from the
|
||||
# latest release so we can compare to the intended state
|
||||
old_chart = old_release['chart']
|
||||
old_values = old_release.get('config', {})
|
||||
|
||||
upgrade = chart.get('upgrade', {})
|
||||
options = upgrade.get('options', {})
|
||||
|
||||
# TODO: Remove when v1 doc support is removed.
|
||||
schema_info = get_schema_info(ch['schema'])
|
||||
if schema_info.version < 2:
|
||||
no_hooks_location = upgrade
|
||||
else:
|
||||
no_hooks_location = options
|
||||
|
||||
disable_hooks = no_hooks_location.get('no_hooks', False)
|
||||
force = options.get('force', False)
|
||||
|
||||
if upgrade:
|
||||
upgrade_pre = upgrade.get('pre', {})
|
||||
upgrade_post = upgrade.get('post', {})
|
||||
|
||||
if not self.disable_update_pre and upgrade_pre:
|
||||
pre_actions = upgrade_pre
|
||||
|
||||
if not self.disable_update_post and upgrade_post:
|
||||
LOG.warning(
|
||||
'Post upgrade actions are ignored by Armada'
|
||||
'and will not affect deployment.')
|
||||
|
||||
LOG.info('Checking for updates to chart release inputs.')
|
||||
new_chart = chartbuilder.get_helm_chart(release_id, values)
|
||||
diff = self.get_diff(old_chart, old_values, new_chart, values)
|
||||
|
||||
if not diff:
|
||||
LOG.info("Found no updates to chart release inputs")
|
||||
else:
|
||||
action = metrics.ChartDeployAction.UPGRADE
|
||||
LOG.info("Found updates to chart release inputs")
|
||||
|
||||
def upgrade():
|
||||
# do actual update
|
||||
timer = int(round(deadline - time.time()))
|
||||
PreUpdateActions(self.helm.k8s).execute(
|
||||
pre_actions, release, namespace, chart, disable_hooks,
|
||||
values, timer)
|
||||
LOG.info(
|
||||
"Upgrading release=%s, wait=%s, "
|
||||
"timeout=%ss", release_id, native_wait_enabled, timer)
|
||||
self.helm.upgrade_release(
|
||||
source_directory,
|
||||
release_id,
|
||||
disable_hooks=disable_hooks,
|
||||
values=values,
|
||||
wait=native_wait_enabled,
|
||||
timeout=timer,
|
||||
force=force)
|
||||
|
||||
LOG.info('Upgrade completed')
|
||||
result['upgrade'] = release_id
|
||||
|
||||
deploy = upgrade
|
||||
else:
|
||||
|
||||
def install():
|
||||
def upgrade():
|
||||
# do actual update
|
||||
timer = int(round(deadline - time.time()))
|
||||
|
||||
LOG.info(
|
||||
"Installing release=%s, wait=%s, "
|
||||
"timeout=%ss", release_id, native_wait_enabled, timer)
|
||||
self.helm.install_release(
|
||||
source_directory,
|
||||
release_id,
|
||||
values=values,
|
||||
wait=native_wait_enabled,
|
||||
timeout=timer)
|
||||
"Upgrading (patching) release=%s, "
|
||||
"timeout=%ss", release_name, timer)
|
||||
|
||||
LOG.info('Install completed')
|
||||
result['install'] = release_id
|
||||
self.k8s.patch_custom_resource(
|
||||
"armada.airshipit.io",
|
||||
"v1",
|
||||
namespace,
|
||||
"armadacharts",
|
||||
release_name,
|
||||
self._gen_crd_template(chart_name, release_id,
|
||||
chart['source']['location'],
|
||||
values, chart.get('wait', {}),
|
||||
chart.get('upgrade', {}).
|
||||
get('pre', {}).get('delete', []),
|
||||
chart.get('test', {}).
|
||||
get('enabled', True))
|
||||
)
|
||||
|
||||
# Check for release with status other than DEPLOYED
|
||||
if status:
|
||||
if status != helm.STATUS_FAILED:
|
||||
LOG.warn(
|
||||
'Unexpected release status encountered '
|
||||
'release=%s, status=%s', release_id, status)
|
||||
LOG.info('Upgrade completed')
|
||||
result['upgrade'] = release_id
|
||||
|
||||
# Make best effort to determine whether a deployment is
|
||||
# likely pending, by checking if the last deployment
|
||||
# was started within the timeout window of the chart.
|
||||
last_deployment_age = r.get_last_deployment_age(
|
||||
old_release)
|
||||
likely_pending = last_deployment_age <= wait_timeout
|
||||
if likely_pending:
|
||||
# We don't take any deploy action and wait for the
|
||||
# to get deployed.
|
||||
deploy = noop
|
||||
deadline = deadline - last_deployment_age
|
||||
else:
|
||||
# Release is likely stuck in an unintended
|
||||
# state. Log and continue on with remediation steps
|
||||
# below.
|
||||
LOG.info(
|
||||
'Old release %s likely stuck in status %s, '
|
||||
'(last deployment age=%ss) >= '
|
||||
'(chart wait timeout=%ss)', release, status,
|
||||
last_deployment_age, wait_timeout)
|
||||
res = self.purge_release(
|
||||
chart, release_id, status, manifest_name,
|
||||
chart_name, result)
|
||||
if isinstance(res, dict):
|
||||
if 'protected' in res:
|
||||
return res
|
||||
action = metrics.ChartDeployAction.INSTALL
|
||||
deploy = install
|
||||
else:
|
||||
# The chart is in Failed state, hence we purge
|
||||
# the chart and attempt to install it again.
|
||||
res = self.purge_release(
|
||||
chart, release_id, status, manifest_name, chart_name,
|
||||
result)
|
||||
if isinstance(res, dict):
|
||||
if 'protected' in res:
|
||||
return res
|
||||
action = metrics.ChartDeployAction.INSTALL
|
||||
deploy = install
|
||||
action = metrics.ChartDeployAction.UPGRADE
|
||||
deploy = upgrade
|
||||
|
||||
if status is None:
|
||||
action = metrics.ChartDeployAction.INSTALL
|
||||
deploy = install
|
||||
except ApiException as err:
|
||||
if err.status == 404:
|
||||
def install():
|
||||
timer = int(round(deadline - time.time()))
|
||||
LOG.info(
|
||||
"Installing release=%s, "
|
||||
"timeout=%ss", release_name, timer)
|
||||
|
||||
self.k8s.create_custom_resource(
|
||||
const.CHART_GROUP,
|
||||
const.CHART_VERSION,
|
||||
namespace,
|
||||
const.CHART_PLURAL,
|
||||
self._gen_crd_template(chart_name, release_id,
|
||||
chart['source']['location'],
|
||||
values, chart.get('wait', {}),
|
||||
chart.get('upgrade', {}).
|
||||
get('pre', {}).get('delete', []),
|
||||
chart.get('test', {}).
|
||||
get('enabled', True)
|
||||
)
|
||||
)
|
||||
|
||||
LOG.info('Install completed')
|
||||
result['install'] = release_id
|
||||
|
||||
action = metrics.ChartDeployAction.INSTALL
|
||||
deploy = install
|
||||
else:
|
||||
raise
|
||||
|
||||
# Deploy
|
||||
with metrics.CHART_DEPLOY.get_context(wait_timeout, manifest_name,
|
||||
|
@ -240,55 +151,76 @@ class ChartDeploy(object):
|
|||
|
||||
# Wait
|
||||
timer = int(round(deadline - time.time()))
|
||||
chart_wait.wait(timer)
|
||||
|
||||
# Test
|
||||
just_deployed = ('install' in result) or ('upgrade' in result)
|
||||
last_test_passed = old_release and r.get_last_test_result(old_release)
|
||||
|
||||
test_handler = Test(
|
||||
chart, release_id, self.helm, cg_test_charts=cg_test_all_charts)
|
||||
|
||||
run_test = test_handler.test_enabled and (
|
||||
just_deployed or not last_test_passed)
|
||||
if run_test:
|
||||
with metrics.CHART_TEST.get_context(test_handler.timeout,
|
||||
manifest_name, chart_name):
|
||||
self._test_chart(test_handler)
|
||||
LOG.info('Starting to wait')
|
||||
self.k8s.wait_custom_resource(const.CHART_GROUP,
|
||||
const.CHART_VERSION,
|
||||
namespace,
|
||||
const.CHART_PLURAL,
|
||||
"{}={}".format(const.CHART_LABEL,
|
||||
release_id.name),
|
||||
timer)
|
||||
|
||||
return result
|
||||
|
||||
def purge_release(
|
||||
self, chart, release_id, status, manifest_name, chart_name,
|
||||
result):
|
||||
protected = chart.get('protected', {})
|
||||
if protected:
|
||||
p_continue = protected.get('continue_processing', False)
|
||||
if p_continue:
|
||||
LOG.warn(
|
||||
'Release %s is `protected`, '
|
||||
'continue_processing=True. Operator must '
|
||||
'handle %s release manually.', release_id, status)
|
||||
result['protected'] = release_id
|
||||
return result
|
||||
else:
|
||||
LOG.error(
|
||||
'Release %s is `protected`, '
|
||||
'continue_processing=False.', release_id)
|
||||
raise armada_exceptions.ProtectedReleaseException(
|
||||
release_id, status)
|
||||
else:
|
||||
# Purge the release
|
||||
with metrics.CHART_DELETE.get_context(manifest_name, chart_name):
|
||||
def _get_timeout(self, ch):
|
||||
chart_data = ch[const.KEYWORD_DATA]
|
||||
wait_config = chart_data.get('wait', {})
|
||||
|
||||
LOG.info(
|
||||
'Purging release %s with status %s', release_id, status)
|
||||
chart_delete = ChartDelete(chart, release_id, self.helm)
|
||||
chart_delete.delete()
|
||||
result['purge'] = release_id
|
||||
# Calculate timeout
|
||||
wait_timeout = self.timeout
|
||||
if wait_timeout is None:
|
||||
wait_timeout = wait_config.get('timeout')
|
||||
|
||||
def _test_chart(self, test_handler):
|
||||
test_handler.test_release()
|
||||
# TODO: Remove when v1 doc support is removed.
|
||||
deprecated_timeout = chart_data.get('timeout')
|
||||
if deprecated_timeout is not None:
|
||||
LOG.warn(
|
||||
'The `timeout` key is deprecated and support '
|
||||
'for this will be removed soon. Use '
|
||||
'`wait.timeout` instead.')
|
||||
if wait_timeout is None:
|
||||
wait_timeout = deprecated_timeout
|
||||
|
||||
def get_diff(self, old_chart, old_values, new_chart, values):
|
||||
return ReleaseDiff(old_chart, old_values, new_chart, values).get_diff()
|
||||
if wait_timeout is None:
|
||||
LOG.info(
|
||||
'No Chart timeout specified, using default: %ss',
|
||||
const.DEFAULT_CHART_TIMEOUT)
|
||||
wait_timeout = const.DEFAULT_CHART_TIMEOUT
|
||||
|
||||
return wait_timeout
|
||||
|
||||
@staticmethod
|
||||
def _convert_min_ready(chart):
|
||||
wait_opts = chart.get('wait', {})
|
||||
if len(wait_opts) > 0:
|
||||
res_opts = wait_opts.get('resources', [])
|
||||
for opt in res_opts:
|
||||
if 'min_ready' in opt:
|
||||
opt['min_ready'] = str(opt['min_ready'])
|
||||
|
||||
@staticmethod
|
||||
def _gen_crd_template(chart_name, release_id, location,
|
||||
values, wait_opts, pre_opts=[], test_enabled=True):
|
||||
return {
|
||||
'apiVersion': const.CHART_APIVERSION,
|
||||
'kind': const.CHART_KIND,
|
||||
'metadata': {
|
||||
'labels': {
|
||||
const.CHART_LABEL: release_id.name
|
||||
},
|
||||
'name': release_id.name,
|
||||
'namespace': release_id.namespace,
|
||||
},
|
||||
'data': {
|
||||
'chart_name': chart_name,
|
||||
'namespace': release_id.namespace,
|
||||
'release': release_id.name,
|
||||
'source': {
|
||||
'location': location,
|
||||
},
|
||||
'values': values,
|
||||
'test': {'enabled': test_enabled},
|
||||
'delete': pre_opts,
|
||||
'wait': wait_opts,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ from oslo_log import log as logging
|
|||
|
||||
from armada.const import DEFAULT_K8S_TIMEOUT
|
||||
from armada.exceptions import k8s_exceptions as exceptions
|
||||
from armada.exceptions import armada_exceptions
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -361,6 +362,13 @@ class K8s(object):
|
|||
timeout = DEFAULT_K8S_TIMEOUT
|
||||
return timeout
|
||||
|
||||
def create_namespace(self, namespace):
|
||||
return self.client.create_namespace(client.V1Namespace(
|
||||
metadata=client.V1ObjectMeta(name=namespace)))
|
||||
|
||||
def read_namespace(self, namespace):
|
||||
return self.client.read_namespace(namespace)
|
||||
|
||||
def create_custom_resource_definition(self, crd):
|
||||
"""Creates a custom resource definition
|
||||
|
||||
|
@ -420,6 +428,9 @@ class K8s(object):
|
|||
return self.custom_objects.get_namespaced_custom_object(
|
||||
group, version, namespace, plural, name)
|
||||
|
||||
def read_custom_resource_definition(self, name):
|
||||
return self.api_extensions.read_custom_resource_definition(name)
|
||||
|
||||
def replace_custom_resource(
|
||||
self, group, version, namespace, plural, name, body):
|
||||
"""Replaces a custom resource
|
||||
|
@ -436,3 +447,58 @@ class K8s(object):
|
|||
"""
|
||||
return self.custom_objects.replace_namespaced_custom_object(
|
||||
group, version, namespace, plural, name, body)
|
||||
|
||||
def patch_custom_resource(
|
||||
self, group, version, namespace, plural, name, body):
|
||||
return self.custom_objects.patch_namespaced_custom_object(
|
||||
group, version, namespace, plural, name, body)
|
||||
|
||||
def wait_custom_resource(
|
||||
self, group, version, namespace, plural, label, timeout=300):
|
||||
|
||||
LOG.warn('starting to wait following params %s %s %s %s %s %s', group,
|
||||
version, namespace, plural, label, timeout)
|
||||
resources = self.custom_objects.list_namespaced_custom_object(
|
||||
group, version, namespace, plural, label_selector=label)
|
||||
ready = False
|
||||
|
||||
if len(resources.get('items', [])) != 1:
|
||||
LOG.warn('No resources found')
|
||||
raise armada_exceptions.WaitException(
|
||||
"Unexpected number of objects to wait")
|
||||
|
||||
for resource in resources.get('items', []):
|
||||
status = resource.get('status', {})
|
||||
resource_name = resource['metadata']['name']
|
||||
conds = status.get('conditions', [])
|
||||
for cond in conds:
|
||||
if cond['type'] == "Ready" and cond['status'] == "True":
|
||||
if status['observedGeneration'] == \
|
||||
resource['metadata']['generation']:
|
||||
LOG.warn('Resource '' is ready already %s',
|
||||
resource_name)
|
||||
ready = True
|
||||
if ready:
|
||||
LOG.warn("nothing to watch, exiting")
|
||||
return
|
||||
|
||||
w = watch.Watch()
|
||||
for event in w.stream(
|
||||
self.custom_objects.list_namespaced_custom_object,
|
||||
group, version, namespace, plural,
|
||||
label_selector=label, timeout_seconds=timeout):
|
||||
|
||||
status = event['object'].get('status', {})
|
||||
LOG.warn('got event object %s ',
|
||||
status)
|
||||
resource_name = event['object']['metadata']['name']
|
||||
conds = status.get('conditions', [])
|
||||
for cond in conds:
|
||||
if cond['type'] == "Ready" and cond['status'] == "True":
|
||||
if status['observedGeneration'] == \
|
||||
event['object']['metadata']['generation']:
|
||||
LOG.warn('Resource is ready %s', resource_name)
|
||||
return
|
||||
|
||||
raise armada_exceptions.ArmadaTimeoutException(
|
||||
"Resource with label {} is not ready".format(label))
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.13.0
|
||||
name: armadacharts.armada.airshipit.io
|
||||
spec:
|
||||
group: armada.airshipit.io
|
||||
names:
|
||||
kind: ArmadaChart
|
||||
listKind: ArmadaChartList
|
||||
plural: armadacharts
|
||||
singular: armadachart
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ArmadaChart is the Schema for the armadacharts API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
data:
|
||||
description: ArmadaChartSpec defines the desired state of ArmadaChart
|
||||
properties:
|
||||
chart_name:
|
||||
description: ChartName is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
type: string
|
||||
delete:
|
||||
description: Delete holds the values for this Helm release.
|
||||
items:
|
||||
description: ArmadaChartDeleteResource defines the wait options
|
||||
of ArmadaChart
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels is an example field of ArmadaChart. Edit
|
||||
armadachart_types.go to remove/update
|
||||
type: object
|
||||
type:
|
||||
description: Type is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
namespace:
|
||||
description: Namespace is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
type: string
|
||||
release:
|
||||
description: Release is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
type: string
|
||||
source:
|
||||
description: Source is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
properties:
|
||||
location:
|
||||
description: Location is an example field of ArmadaChart. Edit
|
||||
armadachart_types.go to remove/update
|
||||
type: string
|
||||
subpath:
|
||||
description: Subpath is an example field of ArmadaChart. Edit
|
||||
armadachart_types.go to remove/update
|
||||
type: string
|
||||
type:
|
||||
description: Type is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
type: string
|
||||
type: object
|
||||
test:
|
||||
description: Test holds the values for this Helm release.
|
||||
properties:
|
||||
enabled:
|
||||
description: Enabled is an example field of ArmadaChart. Edit
|
||||
armadachart_types.go to remove/update
|
||||
type: boolean
|
||||
type: object
|
||||
values:
|
||||
description: Values holds the values for this Helm release.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
wait:
|
||||
description: Wait holds the values for this Helm release.
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels is an example field of ArmadaChart. Edit armadachart_types.go
|
||||
to remove/update
|
||||
type: object
|
||||
native:
|
||||
description: ArmadaChartWaitNative defines the wait options of
|
||||
ArmadaChart
|
||||
properties:
|
||||
enabled:
|
||||
description: Enabled is an example field of ArmadaChart. Edit
|
||||
armadachart_types.go to remove/update
|
||||
type: boolean
|
||||
type: object
|
||||
resources:
|
||||
items:
|
||||
description: ArmadaChartWaitResource defines the wait options
|
||||
of ArmadaChart
|
||||
properties:
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels is an example field of ArmadaChart.
|
||||
Edit armadachart_types.go to remove/update
|
||||
type: object
|
||||
min_ready:
|
||||
type: string
|
||||
type:
|
||||
description: Type is an example field of ArmadaChart. Edit
|
||||
armadachart_types.go to remove/update
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
timeout:
|
||||
description: Timeout is the time to wait for full reconciliation
|
||||
of Helm release.
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
status:
|
||||
description: ArmadaChartStatus defines the observed state of ArmadaChart
|
||||
properties:
|
||||
conditions:
|
||||
description: Conditions holds the conditions for the ArmadaChart.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\n type FooStatus struct{ // Represents the observations of a
|
||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
failures:
|
||||
description: Failures is the reconciliation failure count against
|
||||
the latest desired state. It is reset after a successful reconciliation.
|
||||
format: int64
|
||||
type: integer
|
||||
helmChart:
|
||||
description: HelmChart is the namespaced name of the HelmChart resource
|
||||
created by the controller for the ArmadaChart.
|
||||
type: string
|
||||
installFailures:
|
||||
description: InstallFailures is the install failure count against
|
||||
the latest desired state. It is reset after a successful reconciliation.
|
||||
format: int64
|
||||
type: integer
|
||||
lastAppliedRevision:
|
||||
description: LastAppliedRevision is the revision of the last successfully
|
||||
applied source.
|
||||
type: string
|
||||
lastAttemptedRevision:
|
||||
description: LastAttemptedRevision is the revision of the last reconciliation
|
||||
attempt.
|
||||
type: string
|
||||
lastAttemptedValuesChecksum:
|
||||
description: LastAttemptedValuesChecksum is the SHA1 checksum of the
|
||||
values of the last reconciliation attempt.
|
||||
type: string
|
||||
lastHandledReconcileAt:
|
||||
description: LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value can
|
||||
be detected.
|
||||
type: string
|
||||
lastReleaseRevision:
|
||||
description: LastReleaseRevision is the revision of the last successful
|
||||
Helm release.
|
||||
type: integer
|
||||
observedGeneration:
|
||||
description: ObservedGeneration is the last observed generation.
|
||||
format: int64
|
||||
type: integer
|
||||
upgradeFailures:
|
||||
description: UpgradeFailures is the upgrade failure count against
|
||||
the latest desired state. It is reset after a successful reconciliation.
|
||||
format: int64
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
|
@ -109,6 +109,43 @@ spec:
|
|||
{{ tuple $envAll "api" $mounts_armada_api_init | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
|
||||
{{ dict "envAll" $envAll "application" "armada" "container" "armada_api_init" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
|
||||
containers:
|
||||
- name: manager
|
||||
{{ tuple $envAll "operator" | include "helm-toolkit.snippets.image" | indent 10 }}
|
||||
{{ tuple $envAll $envAll.Values.pod.resources.api | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
|
||||
command:
|
||||
- /manager
|
||||
args:
|
||||
- '--health-probe-bind-address=:8081'
|
||||
- '--metrics-bind-address=127.0.0.1:8080'
|
||||
- '--leader-elect'
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8081
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 15
|
||||
timeoutSeconds: 1
|
||||
periodSeconds: 20
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: 8081
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
allowPrivilegeEscalation: false
|
||||
- name: armada-api
|
||||
{{ tuple $envAll "api" | include "helm-toolkit.snippets.image" | indent 10 }}
|
||||
{{ tuple $envAll $envAll.Values.pod.resources.api | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
|
||||
|
|
|
@ -29,6 +29,7 @@ labels:
|
|||
images:
|
||||
tags:
|
||||
api: 'quay.io/airshipit/armada:latest'
|
||||
operator: 'quay.io/raliev12/armada-controller:latest'
|
||||
dep_check: 'quay.io/stackanetes/kubernetes-entrypoint:v0.3.1'
|
||||
ks_endpoints: 'docker.io/openstackhelm/heat:newton'
|
||||
ks_service: 'docker.io/openstackhelm/heat:newton'
|
||||
|
|
Loading…
Reference in New Issue