Add tempest role

Sem-Ver: feature
Change-Id: I2bc7f206cda99b76aa8bc23b864f53120de27185
diff --git a/doc/source/roles/openstack_helm_tempest/index.rst b/doc/source/roles/openstack_helm_tempest/index.rst
new file mode 100644
index 0000000..5a084e5
--- /dev/null
+++ b/doc/source/roles/openstack_helm_tempest/index.rst
@@ -0,0 +1,10 @@
+.. Copyright (C) 2022 VEXXHOST, Inc.
+.. SPDX-License-Identifier: Apache-2.0
+
+``openstack_helm_tempest``
+============================
+
+.. toctree::
+   :maxdepth: 2
+
+   defaults/main
\ No newline at end of file
diff --git a/molecule/default/heat/server.yaml b/molecule/default/heat/server.yaml
index 930868f..53a9c5f 100644
--- a/molecule/default/heat/server.yaml
+++ b/molecule/default/heat/server.yaml
@@ -43,11 +43,6 @@
     constraints:
       - custom_constraint: nova.keypair
 
-  security_group:
-    type: string
-    constraints:
-      - custom_constraint: neutron.security_group
-
   public_network:
     type: string
     default: public
@@ -91,8 +86,7 @@
     type: OS::Neutron::Port
     properties:
       network: { get_param: external_network }
-      security_groups:
-        - { get_param: security_group }
+      port_security_enabled: false
 
   server:
     type: OS::Nova::Server
diff --git a/molecule/default/heat/stack.yaml b/molecule/default/heat/stack.yaml
index 5bd59dd..55b0bf7 100644
--- a/molecule/default/heat/stack.yaml
+++ b/molecule/default/heat/stack.yaml
@@ -46,17 +46,6 @@
       - custom_constraint: nova.flavor
 
 resources:
-  security_group:
-    type: OS::Neutron::SecurityGroup
-    properties:
-      rules:
-        - protocol: tcp
-          remote_ip_prefix: 0.0.0.0/0
-        - protocol: udp
-          remote_ip_prefix: 0.0.0.0/0
-        - protocol: icmp
-          remote_ip_prefix: 0.0.0.0/0
-
   router:
     type: OS::Neutron::Router
     properties:
@@ -131,7 +120,6 @@
           image: { get_param: image }
           instance_type: { get_param: instance_type }
           key_name: { get_resource: key_pair }
-          security_group: { get_resource: security_group }
           internal_network: { get_resource: internal_network }
           public_network: { get_param: public_network }
           external_network: { get_resource: external_network }
@@ -150,7 +138,6 @@
           image: { get_param: image }
           instance_type: { get_param: instance_type }
           key_name: { get_resource: key_pair }
-          security_group: { get_resource: security_group }
           internal_network: { get_resource: internal_network }
           public_network: { get_param: public_network }
           external_network: { get_resource: external_network }
@@ -171,7 +158,6 @@
           image: { get_param: image }
           instance_type: { get_param: instance_type }
           key_name: { get_resource: key_pair }
-          security_group: { get_resource: security_group }
           internal_network: { get_resource: internal_network }
           public_network: { get_param: public_network }
           external_network: { get_resource: external_network }
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
index 9d4dfe7..78e4152 100644
--- a/molecule/default/molecule.yml
+++ b/molecule/default/molecule.yml
@@ -48,4 +48,4 @@
       host_vars: "${MOLECULE_SCENARIO_DIRECTORY}/host_vars"
       group_vars: "${MOLECULE_SCENARIO_DIRECTORY}/group_vars"
 verifier:
-  name: testinfra
+  name: ansible
diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml
new file mode 100644
index 0000000..79bed89
--- /dev/null
+++ b/molecule/default/verify.yml
@@ -0,0 +1,15 @@
+# Copyright (c) 2022 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.
+
+- import_playbook: vexxhost.atmosphere.tempest
diff --git a/playbooks/generate_workspace.yml b/playbooks/generate_workspace.yml
index b3b7cf1..66dcd25 100644
--- a/playbooks/generate_workspace.yml
+++ b/playbooks/generate_workspace.yml
@@ -273,7 +273,7 @@
             subnets:
               - name: public-subnet
                 cidr: 10.96.250.0/24
-                gateway_ip: 10.96.250.1
+                gateway_ip: 10.96.250.10
                 allocation_pool_start: 10.96.250.200
                 allocation_pool_end: 10.96.250.220
                 dns_nameservers:
diff --git a/playbooks/tempest.yml b/playbooks/tempest.yml
new file mode 100644
index 0000000..c633817
--- /dev/null
+++ b/playbooks/tempest.yml
@@ -0,0 +1,21 @@
+# Copyright (c) 2022 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.
+
+- hosts: controllers[0]
+  gather_facts: false
+  become: true
+  roles:
+    - role: openstack_helm_tempest
+      tags:
+        - openstack-helm-tempest
diff --git a/releasenotes/notes/tempest-add-role-efd573d775e96638.yaml b/releasenotes/notes/tempest-add-role-efd573d775e96638.yaml
new file mode 100644
index 0000000..8426769
--- /dev/null
+++ b/releasenotes/notes/tempest-add-role-efd573d775e96638.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - Added ansible role to deploy tempest
diff --git a/roles/openstack_helm_endpoints/defaults/main.yml b/roles/openstack_helm_endpoints/defaults/main.yml
index 1fef800..70aa15c 100644
--- a/roles/openstack_helm_endpoints/defaults/main.yml
+++ b/roles/openstack_helm_endpoints/defaults/main.yml
@@ -407,3 +407,15 @@
 openstack_helm_endpoints_horizon_mariadb_password: "{{ undef(hint='You must specify a Horizon MariaDB password') }}"
 
                                                                    # ]]]
+# .. envvar:: openstack_helm_endpoints_tempest_region_name [[[
+#
+# Region name for service
+openstack_helm_endpoints_tempest_region_name: "{{ openstack_helm_endpoints_region_name }}"
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_endpoints_tempest_keystone_password [[[
+#
+# Keystone password for service
+openstack_helm_endpoints_tempest_keystone_password: "{{ undef(hint='You must specify a Tempest Keystone password') }}"
+
+                                                                   # ]]]
diff --git a/roles/openstack_helm_endpoints/vars/main.yml b/roles/openstack_helm_endpoints/vars/main.yml
index f575e92..cc77ab1 100644
--- a/roles/openstack_helm_endpoints/vars/main.yml
+++ b/roles/openstack_helm_endpoints/vars/main.yml
@@ -401,3 +401,11 @@
     auth:
       horizon:
         password: "{{ openstack_helm_endpoints_horizon_mariadb_password }}"
+
+_openstack_helm_endpoints_tempest:
+  identity:
+    auth:
+      tempest:
+        region_name: "{{ openstack_helm_endpoints_tempest_region_name }}"
+        username: "tempest-{{ openstack_helm_endpoints_tempest_region_name }}"
+        password: "{{ openstack_helm_endpoints_tempest_keystone_password }}"
diff --git a/roles/openstack_helm_tempest/defaults/main.yml b/roles/openstack_helm_tempest/defaults/main.yml
new file mode 100644
index 0000000..6ccf3b3
--- /dev/null
+++ b/roles/openstack_helm_tempest/defaults/main.yml
@@ -0,0 +1,55 @@
+---
+# .. vim: foldmarker=[[[,]]]:foldmethod=marker
+
+# .. Copyright (C) 2022 VEXXHOST, Inc.
+# .. SPDX-License-Identifier: Apache-2.0
+
+# Default variables
+# =================
+
+# .. contents:: Sections
+#    :local:
+
+
+# .. envvar:: openstack_helm_tempest_chart_repo_name [[[
+#
+# Helm repository name for the chart.
+openstack_helm_tempest_chart_repo_name: openstack-helm
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_tempest_chart_repo_url [[[
+#
+# Helm repository URL for the chart.
+openstack_helm_tempest_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_tempest_chart_name [[[
+#
+# Helm chart name (will also be used for release name)
+openstack_helm_tempest_chart_name: tempest
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_tempest_image_repository [[[
+#
+# Image repository location to be prefixed for all images
+openstack_helm_tempest_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_tempest_image_tag [[[
+#
+# Image tag for container
+openstack_helm_tempest_image_tag: 30.1.0-4
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_tempest_heat_image_tag [[[
+#
+# Image tag for Heat to be used for jobs running via Helm hooks
+openstack_helm_tempest_heat_image_tag: wallaby
+
+                                                                   # ]]]
+# .. envvar:: openstack_helm_tempest_values [[[
+#
+# Overrides for Helm chart values
+openstack_helm_tempest_values: {}
+
+                                                                   # ]]]
diff --git a/roles/openstack_helm_tempest/meta/main.yml b/roles/openstack_helm_tempest/meta/main.yml
new file mode 100644
index 0000000..d9b9461
--- /dev/null
+++ b/roles/openstack_helm_tempest/meta/main.yml
@@ -0,0 +1,29 @@
+# Copyright (c) 2022 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.
+
+galaxy_info:
+  author: VEXXHOST, Inc.
+  description: Ansible role for OpenStack Tempest
+  license: Apache-2.0
+  min_ansible_version: 5.5.0
+  platforms:
+    - name: Ubuntu
+      versions:
+        - focal
+
+dependencies:
+  - role: helm_repository
+    vars:
+      helm_repository_name: "{{ openstack_helm_tempest_chart_repo_name }}"
+      helm_repository_repo_url: "{{ openstack_helm_tempest_chart_repo_url }}"
diff --git a/roles/openstack_helm_tempest/tasks/main.yml b/roles/openstack_helm_tempest/tasks/main.yml
new file mode 100644
index 0000000..4094809
--- /dev/null
+++ b/roles/openstack_helm_tempest/tasks/main.yml
@@ -0,0 +1,141 @@
+# Copyright (c) 2022 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.
+
+- name: Generate OpenStack-Helm endpoints
+  ansible.builtin.include_role:
+    name: openstack_helm_endpoints
+  vars:
+    openstack_helm_endpoints_repo_name: "{{ openstack_helm_tempest_chart_repo_name }}"
+    openstack_helm_endpoints_repo_url: "{{ openstack_helm_tempest_chart_repo_url }}"
+    openstack_helm_endpoints_chart: "{{ openstack_helm_tempest_chart_name }}"
+
+- name: Configure tempest
+  block:
+    - name: Get test image object
+      openstack.cloud.image_info:
+        auth:
+          auth_url: "https://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}"
+          username: "{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
+          password: "{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
+          project_name: admin
+          user_domain_name: Default
+          project_domain_name: Default
+        image: cirros
+      register: _openstack_helm_tempest_test_image
+      when: openstack_helm_tempest_values.conf.tempest.compute.image_ref is not defined
+
+    - name: Configure test image ref
+      ansible.builtin.set_fact:
+        openstack_helm_tempest_values: "{{ openstack_helm_tempest_values | default({}) | combine({item.key: item.value}, recursive=True) }}"
+      with_dict:
+        conf:
+          tempest:
+            compute:
+              image_ref: "{{ _openstack_helm_tempest_test_image.openstack_image.id }}"
+      when:
+        - openstack_helm_tempest_values.conf.tempest.compute.image_ref is not defined
+        - _openstack_helm_tempest_test_image.openstack_image.id is defined
+
+    - name: Get test flavor object
+      openstack.cloud.compute_flavor_info:
+        auth:
+          auth_url: "https://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}"
+          username: "{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
+          password: "{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
+          project_name: admin
+          user_domain_name: Default
+          project_domain_name: Default
+        name: m1.tiny
+      register: _openstack_helm_tempest_test_flavor
+      when: openstack_helm_tempest_values.conf.tempest.compute.flavor_ref is not defined
+
+    - name: Set test flavor ref
+      ansible.builtin.set_fact:
+        openstack_helm_tempest_values: "{{ openstack_helm_tempest_values | default({}) | combine({item.key: item.value}, recursive=True) }}"
+      with_dict:
+        conf:
+          tempest:
+            compute:
+              flavor_ref: "{{ _openstack_helm_tempest_test_flavor.openstack_flavors[0].id }}"
+      when:
+        - openstack_helm_tempest_values.conf.tempest.compute.flavor_ref is not defined
+        - _openstack_helm_tempest_test_flavor.openstack_flavors[0].id is defined
+
+    - name: Get test network object
+      openstack.cloud.networks_info:
+        auth:
+          auth_url: "https://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}"
+          username: "{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
+          password: "{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
+          project_name: admin
+          user_domain_name: Default
+          project_domain_name: Default
+        name: public
+      register: _openstack_helm_tempest_test_network
+      when: openstack_helm_tempest_values.conf.tempest.network.public_network_id is not defined
+
+    - name: Set test network ref
+      ansible.builtin.set_fact:
+        openstack_helm_tempest_values: "{{ openstack_helm_tempest_values | default({}) | combine({item.key: item.value}, recursive=True) }}"
+      with_dict:
+        conf:
+          tempest:
+            network:
+              public_network_id: "{{ _openstack_helm_tempest_test_network.openstack_networks[0].id }}"
+      when:
+        - openstack_helm_tempest_values.conf.tempest.network.public_network_id is not defined
+        - _openstack_helm_tempest_test_network.openstack_networks[0].id is defined
+
+- name: Deploy Helm chart
+  kubernetes.core.helm:
+    name: "{{ openstack_helm_tempest_chart_name }}"
+    chart_ref: "{{ openstack_helm_tempest_chart_repo_name }}/{{ openstack_helm_tempest_chart_name }}"
+    chart_version: 0.2.3
+    release_namespace: openstack
+    kubeconfig: /etc/kubernetes/admin.conf
+    wait: true
+    wait_timeout: 20m
+    values: "{{ _openstack_helm_tempest_values | combine(openstack_helm_tempest_values, recursive=True) }}"
+
+- name: Get tempest job object
+  kubernetes.core.k8s_info:
+    api_version: batch/v1
+    kind: Job
+    name: tempest-run-tests
+    namespace: openstack
+  register: _tempest_job_obj
+
+- name: Get tempest log
+  kubernetes.core.k8s_log:
+    namespace: openstack
+    label_selectors:
+      - job-name=tempest-run-tests
+  register: _tempest_log
+
+- name: Print success tempest result
+  ansible.builtin.debug:
+    msg: "Tempest success!"
+  when:
+    - _tempest_job_obj.resources[0]['status']['succeeded'] is defined
+    - _tempest_job_obj.resources[0]['status']['succeeded'] == 1
+
+- name: Print failed tempest result
+  ansible.builtin.debug:
+    msg: "Tempest failed!"
+  when: _tempest_job_obj.resources[0]['status']['succeeded'] is not defined or
+        _tempest_job_obj.resources[0]['status']['succeeded'] != 1
+
+- name: Print tempest log details
+  ansible.builtin.debug:
+    msg: "{{ _tempest_log.log_lines }}"
diff --git a/roles/openstack_helm_tempest/vars/main.yml b/roles/openstack_helm_tempest/vars/main.yml
new file mode 100644
index 0000000..8a97656
--- /dev/null
+++ b/roles/openstack_helm_tempest/vars/main.yml
@@ -0,0 +1,55 @@
+# Copyright (c) 2022 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.
+
+_openstack_helm_tempest_values:
+  endpoints: "{{ openstack_helm_endpoints }}"
+  images:
+    tags:
+      dep_check: "{{ openstack_helm_tempest_image_repository }}/kubernetes-entrypoint:latest"
+      tempest_run_tests: "{{ openstack_helm_tempest_image_repository }}/tempest:{{ openstack_helm_tempest_image_tag }}"
+      ks_user: "{{ openstack_helm_tempest_image_repository }}/heat:{{ openstack_helm_tempest_heat_image_tag }}"
+  jobs:
+    run_tests:
+      restartPolicy: Never
+      backoffLimit: 0
+  conf:
+    tempest:
+      service_available:
+        cinder: true
+        glance: true
+        horizon: true
+        neutron: true
+        nova: true
+        swift: false
+      compute:
+        endpoint_type: internal
+        fixed_network_name: public
+      dashboard:
+        dashboard_url: "http://horizon-int.openstack.svc.cluster.local"
+      image:
+        endpoint_type: internal
+      network:
+        endpoint_type: internal
+        floating_network_name: public
+        shared_physical_network: false
+      placement:
+        endpoint_type: internal
+      validation:
+        image_ssh_user: cirros
+      volume:
+        endpoint_type: internal
+      object-storage:
+        endpoint_type: internal
+  pvc:
+    enabled: false