From 4543e907e7bc44ceb2eafd4c67d3cee3a08baf78 Mon Sep 17 00:00:00 2001 From: Ruslan Aliev Date: Tue, 7 Nov 2023 23:50:43 -0600 Subject: [PATCH] [DNM] Operator test Signed-off-by: Ruslan Aliev Change-Id: I76fb41062d152bf360a85d781c19ab5b204769b8 --- armada/const.py | 7 + armada/handlers/armada.py | 41 ++- armada/handlers/chart_deploy.py | 332 ++++++++------------ armada/handlers/k8s.py | 66 ++++ armadacharts_crd.yaml | 259 +++++++++++++++ charts/armada/templates/deployment-api.yaml | 37 +++ charts/armada/values.yaml | 1 + 7 files changed, 531 insertions(+), 212 deletions(-) create mode 100644 armadacharts_crd.yaml diff --git a/armada/const.py b/armada/const.py index 62ec4e18..3234971a 100644 --- a/armada/const.py +++ b/armada/const.py @@ -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 diff --git a/armada/handlers/armada.py b/armada/handlers/armada.py index 4dfa6c5e..0293ce50 100644 --- a/armada/handlers/armada.py +++ b/armada/handlers/armada.py @@ -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.') diff --git a/armada/handlers/chart_deploy.py b/armada/handlers/chart_deploy.py index b0303616..bc1a8554 100644 --- a/armada/handlers/chart_deploy.py +++ b/armada/handlers/chart_deploy.py @@ -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 (replacing) release=%s, " + "timeout=%ss", release_name, timer) - LOG.info('Install completed') - result['install'] = release_id + self.k8s.replace_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, + } + } diff --git a/armada/handlers/k8s.py b/armada/handlers/k8s.py index f9317176..a666dd7e 100644 --- a/armada/handlers/k8s.py +++ b/armada/handlers/k8s.py @@ -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)) diff --git a/armadacharts_crd.yaml b/armadacharts_crd.yaml new file mode 100644 index 00000000..9f337d41 --- /dev/null +++ b/armadacharts_crd.yaml @@ -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: {} diff --git a/charts/armada/templates/deployment-api.yaml b/charts/armada/templates/deployment-api.yaml index 5e930311..adf6d5d0 100644 --- a/charts/armada/templates/deployment-api.yaml +++ b/charts/armada/templates/deployment-api.yaml @@ -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 }} diff --git a/charts/armada/values.yaml b/charts/armada/values.yaml index d99d60e5..79a347b6 100644 --- a/charts/armada/values.yaml +++ b/charts/armada/values.yaml @@ -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'