diff --git a/senlin/templates/bin/_senlin-test.sh.tpl b/senlin/templates/bin/_senlin-test.sh.tpl new file mode 100644 index 0000000000..82ee6089e7 --- /dev/null +++ b/senlin/templates/bin/_senlin-test.sh.tpl @@ -0,0 +1,141 @@ +#!/bin/bash + +{{/* +Copyright 2017 The Openstack-Helm 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. +*/}} + +set -ex + +# Set defaults to use for testing. +: ${IMAGE_ID:="$(openstack image show -f value -c id \ + $(openstack image list -f csv | awk -F ',' '{ print $2 "," $1 }' | \ + grep "^\"Cirros" | head -1 | awk -F ',' '{ print $2 }' | tr -d '"'))"} +: ${FLAVOR_ID:="$(openstack flavor show m1.tiny -f value -c id)"} +: ${NETWORK_NAME:="public"} +: ${SUB_TIMEOUT:=1200} + +# Define functions to use during tests. +function gen_uuid () { + cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1 +} + +function wait_for_senlin_cluster { + set +x + end=$(($(date +%s) + ${SUB_TIMEOUT})) + while true; do + STATE=$(openstack cluster show "${1}" -f value -c status) + [ "x${STATE}" == "xACTIVE" ] && break + sleep 1 + now=$(date +%s) + [ $now -gt $end ] && echo "Node did not come up in time" && openstack cluster show "${1}" && exit -1 + done + set -x + openstack cluster show "${1}" +} + +function wait_for_senlin_node { + set +x + end=$(($(date +%s) + ${SUB_TIMEOUT})) + while true; do + STATE=$(openstack cluster node show "${1}" -f value -c status) + [ "x${STATE}" == "xACTIVE" ] && break + sleep 1 + now=$(date +%s) + [ $now -gt $end ] && echo "Node did not come up in time" && openstack cluster node show "${1}" && exit -1 + done + set -x + openstack cluster node show "${1}" +} + +function wait_for_senlin_profile_delete { + set +x + end=$(($(date +%s) + ${SUB_TIMEOUT})) + until openstack cluster profile delete "${1}" --force; do + sleep 1 + now=$(date +%s) + [ $now -gt $end ] && echo "Profile did not delete in time" && exit -1 + done + set -x +} + +# Start test run. +SENLIN_CLUSTER_PROFILE=$(gen_uuid) +SENLIN_CLUSTER_NAME=$(gen_uuid) +SENLIN_NODE_NAME=$(gen_uuid) + +# Create a cluster profile. +tee > /tmp/cirros_basic.yaml < /tmp/test_file +EOF +openstack cluster profile create --spec-file /tmp/cirros_basic.yaml "${SENLIN_CLUSTER_PROFILE}" + +# Create a 0 node cluster using the profile. +# NOTE(portdirect): There is a bug in the Newton era osc/senlin client +# interaction, so we fall back to calling senlin client directly to create +# a cluster, before outright failing. +openstack cluster create --profile "${SENLIN_CLUSTER_PROFILE}" "${SENLIN_CLUSTER_NAME}" || \ + senlin cluster-create -p "${SENLIN_CLUSTER_PROFILE}" "${SENLIN_CLUSTER_NAME}" || false + +# Resize the cluster to contain a node. +openstack cluster resize --capacity 1 "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_cluster "${SENLIN_CLUSTER_NAME}" + +# Expand the cluster by one node. +openstack cluster expand "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_cluster "${SENLIN_CLUSTER_NAME}" + +# Shrink the cluster by one node. +openstack cluster shrink "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_cluster "${SENLIN_CLUSTER_NAME}" + +# Create a single node using the cluster profile. +# NOTE(portdirect): There is a bug in the Newton era osc/senlin client +# interaction, so we fall back to calling senlin client directly to create +# a node, before outright failing. +openstack cluster node create --profile "${SENLIN_CLUSTER_PROFILE}" "${SENLIN_NODE_NAME}" || \ + senlin node-create -p "${SENLIN_CLUSTER_PROFILE}" "${SENLIN_NODE_NAME}" || false +wait_for_senlin_node "${SENLIN_NODE_NAME}" + +# Add the node to the cluster. +openstack cluster members add --nodes "${SENLIN_NODE_NAME}" "${SENLIN_CLUSTER_NAME}" +openstack cluster members list "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_cluster "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_node "${SENLIN_NODE_NAME}" + +# Remove the node from the cluster. +openstack cluster members del --nodes "${SENLIN_NODE_NAME}" "${SENLIN_CLUSTER_NAME}" +openstack cluster members list "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_cluster "${SENLIN_CLUSTER_NAME}" +wait_for_senlin_node "${SENLIN_NODE_NAME}" + +# Cleanup the resources created. +openstack cluster node delete "${SENLIN_NODE_NAME}" --force +openstack cluster delete "${SENLIN_CLUSTER_NAME}" --force +wait_for_senlin_profile_delete "${SENLIN_CLUSTER_PROFILE}" + +echo 'Tests Passed' diff --git a/senlin/templates/configmap-bin.yaml b/senlin/templates/configmap-bin.yaml index cfe6c6cfba..6a75f40276 100644 --- a/senlin/templates/configmap-bin.yaml +++ b/senlin/templates/configmap-bin.yaml @@ -16,6 +16,7 @@ limitations under the License. {{- if .Values.manifests.configmap_bin }} {{- $envAll := . }} +{{- $rallyTests := .Values.conf.rally_tests }} --- apiVersion: v1 kind: ConfigMap @@ -26,6 +27,8 @@ data: bootstrap.sh: | {{ tuple "bin/_bootstrap.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }} {{- end }} + senlin-test.sh: | +{{ tuple "bin/_senlin-test.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }} db-init.py: | {{- include "helm-toolkit.scripts.db_init" . | indent 4 }} db-sync.sh: | diff --git a/senlin/templates/configmap-etc.yaml b/senlin/templates/configmap-etc.yaml index 1ec2cf8859..88f5cc406d 100644 --- a/senlin/templates/configmap-etc.yaml +++ b/senlin/templates/configmap-etc.yaml @@ -89,6 +89,8 @@ kind: ConfigMap metadata: name: senlin-etc data: + rally_tests.yaml: | +{{ toYaml .Values.conf.rally_tests.tests | indent 4 }} senlin.conf: | {{ include "helm-toolkit.utils.to_oslo_conf" .Values.conf.senlin | indent 4 }} api-paste.ini: | diff --git a/senlin/templates/pod-test.yaml b/senlin/templates/pod-test.yaml new file mode 100644 index 0000000000..ac6779ef95 --- /dev/null +++ b/senlin/templates/pod-test.yaml @@ -0,0 +1,61 @@ +{{/* +Copyright 2017 The Openstack-Helm 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. +*/}} + +{{- if .Values.manifests.pod_test }} +{{- $envAll := . }} +{{- $dependencies := .Values.dependencies.static.tests }} + +{{- $mounts_senlin_tests := .Values.pod.mounts.senlin_tests.senlin_tests }} +{{- $mounts_senlin_tests_init := .Values.pod.mounts.senlin_tests.init_container }} + +{{- $serviceAccountName := print .Release.Name "-test" }} +{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }} +--- +apiVersion: v1 +kind: Pod +metadata: + name: "{{.Release.Name}}-test" + annotations: + "helm.sh/hook": test-success +spec: + serviceAccountName: {{ $serviceAccountName }} + nodeSelector: + {{ .Values.labels.test.node_selector_key }}: {{ .Values.labels.test.node_selector_value }} + restartPolicy: Never + initContainers: +{{ tuple $envAll $dependencies $mounts_senlin_tests_init | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }} + containers: + - name: {{.Release.Name}}-senlin-test + image: {{ .Values.images.tags.scripted_test }} + env: +{{- with $env := dict "ksUserSecret" .Values.secrets.identity.admin }} +{{- include "helm-toolkit.snippets.keystone_openrc_env_vars" $env | indent 8 }} +{{- end }} + command: + - /tmp/senlin-test.sh + volumeMounts: + - name: senlin-bin + mountPath: /tmp/senlin-test.sh + subPath: senlin-test.sh + readOnly: true +{{ if $mounts_senlin_tests.volumeMounts }}{{ toYaml $mounts_senlin_tests.volumeMounts | indent 8 }}{{ end }} + volumes: + - name: senlin-bin + configMap: + name: senlin-bin + defaultMode: 0555 +{{ if $mounts_senlin_tests.volumes }}{{ toYaml $mounts_senlin_tests.volumes | indent 4 }}{{ end }} +{{- end }} diff --git a/senlin/values.yaml b/senlin/values.yaml index d7f5b0ccdc..8956beed33 100644 --- a/senlin/values.yaml +++ b/senlin/values.yaml @@ -27,11 +27,15 @@ labels: job: node_selector_key: openstack-control-plane node_selector_value: enabled + test: + node_selector_key: openstack-control-plane + node_selector_value: enabled release_group: null images: tags: + scripted_test: docker.io/openstackhelm/heat:newton bootstrap: docker.io/openstackhelm/heat:newton db_init: docker.io/openstackhelm/heat:newton senlin_db_sync: docker.io/openstackhelm/senlin:newton @@ -54,6 +58,31 @@ jobs: failed: 1 conf: + rally_tests: + run_tempest: false + tests: + SenlinClusters.create_and_delete_cluster: + - args: + desired_capacity: 3 + min_size: 0 + max_size: 5 + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + context: + profiles: + type: os.nova.server + version: "1.0" + properties: + name: cirros_server + flavor: 689eeda3-c6cd-450f-b000-58025c783763 + image: df0c1a14-0940-4ae5-be5c-bb06aa407da2 + networks: + - network: public paste: pipeline:senlin-api: pipeline: request_id faultwrap ssl versionnegotiation webhook authtoken context trust apiv1app @@ -232,6 +261,12 @@ dependencies: services: - endpoint: internal service: oslo_messaging + tests: + services: + - endpoint: internal + service: identity + - endpoint: internal + service: clustering # Names of secrets used by bootstrap and environmental checks @@ -269,6 +304,14 @@ endpoints: project_name: service user_domain_name: default project_domain_name: default + test: + role: admin + region_name: RegionOne + username: test + password: password + project_name: test + user_domain_name: default + project_domain_name: default hosts: default: keystone-api public: keystone @@ -373,6 +416,9 @@ pod: senlin_engine_cleaner: init_container: null senlin_engine_cleaner: + senlin_tests: + init_container: null + senlin_tests: replicas: api: 1 engine: 1 @@ -494,6 +540,7 @@ manifests: job_ks_user: true job_rabbit_init: true pdb_api: true + pod_test: true secret_db: true secret_keystone: true secret_rabbitmq: true