From b1cf61133c22042393b1aa88ec7e2acce903644f Mon Sep 17 00:00:00 2001 From: okozachenko Date: Thu, 20 Aug 2020 19:13:53 +0300 Subject: [PATCH] Rearrange heat templates Change-Id: I82e2bde9646a2ed6eaa8a354c5ce79974342c852 --- openstack_operator/heat.py | 20 ++-- .../templates/heat/api-cfn/daemonset.yml.j2 | 99 +++++++++++++++++++ .../heat/{ => api-cfn}/service.yml.j2 | 8 +- .../templates/heat/api/daemonset.yml.j2 | 99 +++++++++++++++++++ .../templates/heat/api/service.yml.j2 | 28 ++++++ .../heat/{ => engine}/daemonset.yml.j2 | 34 ++----- openstack_operator/tests/unit/test_heat.py | 62 ++++++++++-- 7 files changed, 301 insertions(+), 49 deletions(-) create mode 100644 openstack_operator/templates/heat/api-cfn/daemonset.yml.j2 rename openstack_operator/templates/heat/{ => api-cfn}/service.yml.j2 (82%) create mode 100644 openstack_operator/templates/heat/api/daemonset.yml.j2 create mode 100644 openstack_operator/templates/heat/api/service.yml.j2 rename openstack_operator/templates/heat/{ => engine}/daemonset.yml.j2 (74%) diff --git a/openstack_operator/heat.py b/openstack_operator/heat.py index edbfa149..9c1b7090 100644 --- a/openstack_operator/heat.py +++ b/openstack_operator/heat.py @@ -39,19 +39,19 @@ def create_or_resume(name, spec, **_): password=utils.generate_password()) utils.create_or_update('heat/rabbitmq.yml.j2', spec=spec) - # deploy heat config_hash = utils.generate_hash(spec) - for component in ("api", "api-cfn"): - utils.create_or_update('heat/daemonset.yml.j2', - name=name, spec=spec, - component=component, - config_hash=config_hash) + # deploy heat api + utils.create_or_update('heat/api/daemonset.yml.j2', spec=spec, + config_hash=config_hash) + utils.create_or_update('heat/api/service.yml.j2') - utils.create_or_update('heat/service.yml.j2', - name=name, component=component) + # deploy heat cfn api + utils.create_or_update('heat/api-cfn/daemonset.yml.j2', spec=spec, + config_hash=config_hash) + utils.create_or_update('heat/api-cfn/service.yml.j2') - utils.create_or_update('heat/daemonset.yml.j2', - name=name, spec=spec, component='engine', + # deploy heat cfn engine + utils.create_or_update('heat/engine/daemonset.yml.j2', spec=spec, config_hash=config_hash) # deploy clean jobs diff --git a/openstack_operator/templates/heat/api-cfn/daemonset.yml.j2 b/openstack_operator/templates/heat/api-cfn/daemonset.yml.j2 new file mode 100644 index 00000000..150a20e5 --- /dev/null +++ b/openstack_operator/templates/heat/api-cfn/daemonset.yml.j2 @@ -0,0 +1,99 @@ +--- +# Copyright 2020 VEXXHOST, Inc. +# +# 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: apps/v1 +kind: DaemonSet +metadata: + name: heat-api-cfn + namespace: openstack + labels: + {{ labels("heat", component="api-cfn") | indent(4) }} +spec: + updateStrategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + {{ labels("heat", component="api-cfn") | indent(6) }} + template: + metadata: + labels: + {{ labels("heat", component="api-cfn") | indent(8) }} + annotations: + checksum/config: "{{ config_hash }}" + spec: + automountServiceAccountToken: false + containers: + - name: heat-api-cfn + image: vexxhost/heat-api-cfn:latest + imagePullPolicy: Always + env: + {% if 'sentryDSN' in spec %} + - name: SENTRY_DSN + value: {{ spec.sentryDSN }} + {% endif %} + - name: OS_DEFAULT__HOST + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {% if env is defined %} + {% for v in env %} + - name: "{{ v.name }}" + value: "{{ v.value }}" + {% endfor %} + {% endif %} + ports: + - name: heat-api-cfn + protocol: TCP + containerPort: 8000 + livenessProbe: + tcpSocket: + port: heat-api-cfn + readinessProbe: + tcpSocket: + port: heat-api-cfn + lifecycle: + preStop: + exec: + command: ["/bin/sleep", "5"] + securityContext: + runAsUser: 65534 + runAsGroup: 65534 + volumeMounts: + - mountPath: /etc/heat + name: config + - name: uwsgi-config + mountPath: /etc/uwsgi + volumes: + - name: config + secret: + secretName: heat-config + - name: uwsgi-config + configMap: + defaultMode: 420 + name: uwsgi-default +{% if 'nodeSelector' in spec %} + nodeSelector: + {{ spec.nodeSelector | to_yaml | indent(8) }} +{% endif %} +{% if 'tolerations' in spec %} + tolerations: + {{ spec.tolerations | to_yaml | indent(8) }} +{% endif %} +{% if 'hostAliases' in spec %} + hostAliases: + {{ spec.hostAliases | to_yaml | indent(8) }} +{% endif %} diff --git a/openstack_operator/templates/heat/service.yml.j2 b/openstack_operator/templates/heat/api-cfn/service.yml.j2 similarity index 82% rename from openstack_operator/templates/heat/service.yml.j2 rename to openstack_operator/templates/heat/api-cfn/service.yml.j2 index ac3611f1..87268fd6 100644 --- a/openstack_operator/templates/heat/service.yml.j2 +++ b/openstack_operator/templates/heat/api-cfn/service.yml.j2 @@ -16,13 +16,13 @@ apiVersion: v1 kind: Service metadata: - name: heat-{{ component }} + name: heat-api-cfn namespace: openstack spec: ports: - - name: heat-{{ component }} + - name: heat-api-cfn protocol: TCP port: 80 - targetPort: heat-{{ component }} + targetPort: heat-api-cfn selector: - {{ labels("heat", name, component) | indent(4) }} + {{ labels("heat", component="api-cfn") | indent(4) }} diff --git a/openstack_operator/templates/heat/api/daemonset.yml.j2 b/openstack_operator/templates/heat/api/daemonset.yml.j2 new file mode 100644 index 00000000..904f2e82 --- /dev/null +++ b/openstack_operator/templates/heat/api/daemonset.yml.j2 @@ -0,0 +1,99 @@ +--- +# Copyright 2020 VEXXHOST, Inc. +# +# 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: apps/v1 +kind: DaemonSet +metadata: + name: heat-api + namespace: openstack + labels: + {{ labels("heat", component="api") | indent(4) }} +spec: + updateStrategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + {{ labels("heat", component="api") | indent(6) }} + template: + metadata: + labels: + {{ labels("heat", component="api") | indent(8) }} + annotations: + checksum/config: "{{ config_hash }}" + spec: + automountServiceAccountToken: false + containers: + - name: heat-api + image: vexxhost/heat-api:latest + imagePullPolicy: Always + env: + {% if 'sentryDSN' in spec %} + - name: SENTRY_DSN + value: {{ spec.sentryDSN }} + {% endif %} + - name: OS_DEFAULT__HOST + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {% if env is defined %} + {% for v in env %} + - name: "{{ v.name }}" + value: "{{ v.value }}" + {% endfor %} + {% endif %} + ports: + - name: heat-api + protocol: TCP + containerPort: 8004 + livenessProbe: + tcpSocket: + port: heat-api + readinessProbe: + tcpSocket: + port: heat-api + lifecycle: + preStop: + exec: + command: ["/bin/sleep", "5"] + securityContext: + runAsUser: 65534 + runAsGroup: 65534 + volumeMounts: + - mountPath: /etc/heat + name: config + - name: uwsgi-config + mountPath: /etc/uwsgi + volumes: + - name: config + secret: + secretName: heat-config + - name: uwsgi-config + configMap: + defaultMode: 420 + name: uwsgi-default +{% if 'nodeSelector' in spec %} + nodeSelector: + {{ spec.nodeSelector | to_yaml | indent(8) }} +{% endif %} +{% if 'tolerations' in spec %} + tolerations: + {{ spec.tolerations | to_yaml | indent(8) }} +{% endif %} +{% if 'hostAliases' in spec %} + hostAliases: + {{ spec.hostAliases | to_yaml | indent(8) }} +{% endif %} diff --git a/openstack_operator/templates/heat/api/service.yml.j2 b/openstack_operator/templates/heat/api/service.yml.j2 new file mode 100644 index 00000000..329a0336 --- /dev/null +++ b/openstack_operator/templates/heat/api/service.yml.j2 @@ -0,0 +1,28 @@ +--- +# Copyright 2020 VEXXHOST, Inc. +# +# 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: v1 +kind: Service +metadata: + name: heat-api + namespace: openstack +spec: + ports: + - name: heat-api + protocol: TCP + port: 80 + targetPort: heat-api + selector: + {{ labels("heat", component="api") | indent(4) }} diff --git a/openstack_operator/templates/heat/daemonset.yml.j2 b/openstack_operator/templates/heat/engine/daemonset.yml.j2 similarity index 74% rename from openstack_operator/templates/heat/daemonset.yml.j2 rename to openstack_operator/templates/heat/engine/daemonset.yml.j2 index 7601bf8e..80535e97 100644 --- a/openstack_operator/templates/heat/daemonset.yml.j2 +++ b/openstack_operator/templates/heat/engine/daemonset.yml.j2 @@ -22,10 +22,10 @@ apiVersion: apps/v1 kind: DaemonSet metadata: - name: heat-{{ component }} + name: heat-engine namespace: openstack labels: - {{ labels("heat", name, component) | indent(4) }} + {{ labels("heat", component="engine") | indent(4) }} spec: updateStrategy: rollingUpdate: @@ -33,20 +33,19 @@ spec: type: RollingUpdate selector: matchLabels: - {{ labels("heat", name, component) | indent(6) }} + {{ labels("heat", component="engine") | indent(6) }} template: metadata: labels: - {{ labels("heat", name, component) | indent(8) }} + {{ labels("heat", component="engine") | indent(8) }} annotations: checksum/config: "{{ config_hash }}" spec: automountServiceAccountToken: false - {% if 'engine' in component %} terminationGracePeriodSeconds: 300 initContainers: - name: db-sync - image: vexxhost/heat-{{ component }}:latest + image: vexxhost/heat-engine:latest imagePullPolicy: Always command: - heat-manage @@ -55,7 +54,7 @@ spec: - mountPath: /etc/heat name: config - name: service-clean - image: vexxhost/heat-{{ component }}:latest + image: vexxhost/heat-engine:latest imagePullPolicy: Always command: - heat-manage @@ -64,10 +63,9 @@ spec: volumeMounts: - mountPath: /etc/heat name: config - {% endif %} containers: - - name: heat-{{ component }} - image: vexxhost/heat-{{ component }}:latest + - name: heat-engine + image: vexxhost/heat-engine:latest imagePullPolicy: Always env: {% if 'sentryDSN' in spec %} @@ -84,22 +82,6 @@ spec: value: "{{ v.value }}" {% endfor %} {% endif %} - {% if 'api' in component %} - ports: - - name: heat-{{ component }} - protocol: TCP - containerPort: {% if component == 'api' %}8004{% else %}8000{% endif%} - livenessProbe: - tcpSocket: - port: heat-{{ component }} - readinessProbe: - tcpSocket: - port: heat-{{ component }} - lifecycle: - preStop: - exec: - command: ["/bin/sleep", "5"] - {% endif %} securityContext: runAsUser: 65534 runAsGroup: 65534 diff --git a/openstack_operator/tests/unit/test_heat.py b/openstack_operator/tests/unit/test_heat.py index 1f3b71a8..126dc7e1 100644 --- a/openstack_operator/tests/unit/test_heat.py +++ b/openstack_operator/tests/unit/test_heat.py @@ -21,10 +21,61 @@ from openstack_operator.tests.unit import base class HeatAPIDaemonsetTestCase(base.DaemonSetTestCase): - """Basic tests for the Daemonset.""" + """Basic tests for the api Daemonset.""" RELEASE_TYPE = 'heat' - TEMPLATE_FILE = 'heat/daemonset.yml.j2' + TEMPLATE_FILE = 'heat/api/daemonset.yml.j2' + PORT_EXPOSED = False + + def test_envvar_default_host_exists(self): + """Ensure that heat api daemonset has OS_DEFAULT__HOST env var + to set the engine host""" + envvar_name_list = [] + envvar_list = \ + self.object['spec']['template']['spec']['containers'][0]["env"] + for envvar in envvar_list: + envvar_name_list.append(envvar["name"]) + self.assertIn('OS_DEFAULT__HOST', envvar_name_list) + + +class HeatAPIServiceTestCase(base.ServiceTestCase): + """Basic tests for the api Service.""" + + RELEASE_TYPE = 'heat' + TEMPLATE_FILE = 'heat/api/service.yml.j2' + + +class HeatAPIcfnDaemonsetTestCase(base.DaemonSetTestCase): + """Basic tests for the api cfn Daemonset.""" + + RELEASE_TYPE = 'heat' + TEMPLATE_FILE = 'heat/api-cfn/daemonset.yml.j2' + PORT_EXPOSED = False + + def test_envvar_default_host_exists(self): + """Ensure that heat api cfn daemonset has OS_DEFAULT__HOST env var + to set the engine host""" + envvar_name_list = [] + envvar_list = \ + self.object['spec']['template']['spec']['containers'][0]["env"] + for envvar in envvar_list: + envvar_name_list.append(envvar["name"]) + self.assertIn('OS_DEFAULT__HOST', envvar_name_list) + + +class HeatAPIcfnServiceTestCase(base.ServiceTestCase): + """Basic tests for the api cfn Service.""" + + RELEASE_TYPE = 'heat' + TEMPLATE_FILE = 'heat/api-cfn/service.yml.j2' + + +class HeatEngineDaemonsetTestCase(base.DaemonSetTestCase): + """Basic tests for the engine Daemonset.""" + + RELEASE_TYPE = 'heat' + TEMPLATE_FILE = 'heat/engine/daemonset.yml.j2' + PORT_EXPOSED = False def test_envvar_default_host_exists(self): """Ensure that heat daemonset has OS_DEFAULT__HOST env var @@ -35,10 +86,3 @@ class HeatAPIDaemonsetTestCase(base.DaemonSetTestCase): for envvar in envvar_list: envvar_name_list.append(envvar["name"]) self.assertIn('OS_DEFAULT__HOST', envvar_name_list) - - -class HeatAPServiceTestCase(base.ServiceTestCase): - """Basic tests for the Service.""" - - RELEASE_TYPE = 'heat' - TEMPLATE_FILE = 'heat/service.yml.j2'