diff --git a/tests/ansible-role-requirements.yml b/tests/ansible-role-requirements.yml index 071e1ab8..db1b9776 100644 --- a/tests/ansible-role-requirements.yml +++ b/tests/ansible-role-requirements.yml @@ -38,10 +38,6 @@ src: https://git.openstack.org/openstack/openstack-ansible-galera_server scm: git version: master -- name: rabbitmq_server - src: https://git.openstack.org/openstack/openstack-ansible-rabbitmq_server - scm: git - version: master - name: os_keystone src: https://git.openstack.org/openstack/openstack-ansible-os_keystone scm: git diff --git a/tests/group_vars/all_containers.yml b/tests/group_vars/all_containers.yml new file mode 100644 index 00000000..a24defd1 --- /dev/null +++ b/tests/group_vars/all_containers.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2016, Rackspace US, 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. + +container_name: "{{ inventory_hostname }}" +physical_host: localhost +properties: + service_name: "{{ inventory_hostname }}" +ansible_become: True +ansible_user: root diff --git a/tests/host_vars/infra1.yml b/tests/host_vars/infra1.yml new file mode 100644 index 00000000..af44c3df --- /dev/null +++ b/tests/host_vars/infra1.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2016, Rackspace US, 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. + +ansible_ssh_host: 10.100.100.101 +container_networks: + management_address: + address: "{{ ansible_ssh_host }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.255.0" + type: "veth" diff --git a/tests/host_vars/swift-proxy.yml b/tests/host_vars/swift-proxy.yml new file mode 100644 index 00000000..570a9d5b --- /dev/null +++ b/tests/host_vars/swift-proxy.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2016, Rackspace US, 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. + +ansible_ssh_host: 10.100.100.102 +storage_address: 10.100.101.102 +container_networks: + management_address: + address: "{{ ansible_ssh_host }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.255.0" + type: "veth" + storage_address: + address: "{{ storage_address }}" + bridge: "br-storage" + interface: "eth2" + netmask: "255.255.255.0" + type: "veth" diff --git a/tests/host_vars/swift-storage1.yml b/tests/host_vars/swift-storage1.yml new file mode 100644 index 00000000..e3cbb99d --- /dev/null +++ b/tests/host_vars/swift-storage1.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2016, Rackspace US, 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. + +ansible_ssh_host: 10.100.100.103 +storage_address: 10.100.101.103 +replication_address: 10.100.102.103 +container_networks: + management_address: + address: "{{ ansible_ssh_host }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.255.0" + type: "veth" + storage_address: + address: "{{ storage_address }}" + bridge: "br-storage" + interface: "eth2" + netmask: "255.255.255.0" + type: "veth" + replication_address: + address: "{{ replication_address }}" + bridge: "br-repl" + interface: "eth3" + netmask: "255.255.255.0" + type: "veth" diff --git a/tests/host_vars/swift-storage2.yml b/tests/host_vars/swift-storage2.yml new file mode 100644 index 00000000..77cb2ef0 --- /dev/null +++ b/tests/host_vars/swift-storage2.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2016, Rackspace US, 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. + +ansible_ssh_host: 10.100.100.104 +storage_address: 10.100.101.104 +replication_address: 10.100.102.104 +container_networks: + management_address: + address: "{{ ansible_ssh_host }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.255.0" + type: "veth" + storage_address: + address: "{{ storage_address }}" + bridge: "br-storage" + interface: "eth2" + netmask: "255.255.255.0" + type: "veth" + replication_address: + address: "{{ replication_address }}" + bridge: "br-repl" + interface: "eth3" + netmask: "255.255.255.0" + type: "veth" diff --git a/tests/host_vars/swift-storage3.yml b/tests/host_vars/swift-storage3.yml new file mode 100644 index 00000000..1a1df354 --- /dev/null +++ b/tests/host_vars/swift-storage3.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2016, Rackspace US, 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. + +ansible_ssh_host: 10.100.100.105 +storage_address: 10.100.101.105 +replication_address: 10.100.102.105 +container_networks: + management_address: + address: "{{ ansible_ssh_host }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.255.0" + type: "veth" + storage_address: + address: "{{ storage_address }}" + bridge: "br-storage" + interface: "eth2" + netmask: "255.255.255.0" + type: "veth" + replication_address: + address: "{{ replication_address }}" + bridge: "br-repl" + interface: "eth3" + netmask: "255.255.255.0" + type: "veth" diff --git a/tests/host_vars/swift-storage4.yml b/tests/host_vars/swift-storage4.yml new file mode 100644 index 00000000..c0c25ab7 --- /dev/null +++ b/tests/host_vars/swift-storage4.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2016, Rackspace US, 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. + +ansible_ssh_host: 10.100.100.106 +storage_address: 10.100.101.106 +replication_address: 10.100.102.106 +container_networks: + management_address: + address: "{{ ansible_ssh_host }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.255.0" + type: "veth" + storage_address: + address: "{{ storage_address }}" + bridge: "br-storage" + interface: "eth2" + netmask: "255.255.255.0" + type: "veth" + replication_address: + address: "{{ replication_address }}" + bridge: "br-repl" + interface: "eth3" + netmask: "255.255.255.0" + type: "veth" diff --git a/tests/inventory b/tests/inventory index f553b302..0016add1 100644 --- a/tests/inventory +++ b/tests/inventory @@ -1,4 +1,64 @@ [all] localhost ansible_connection=local ansible_become=True +infra1 +swift-proxy +swift-storage1 +swift-storage2 +swift-storage3 +swift-storage4 + +[all_containers] +infra1 +swift-proxy +swift-storage1 +swift-storage2 +swift-storage3 +swift-storage4 + +[galera_all] +infra1 + +[memcached_all] +infra1 + +[service_all:children] +galera_all +memcached_all + +[keystone_all] +infra1 + +[swift_hosts] +swift-storage1 +swift-storage2 +swift-storage3 +swift-storage4 + +[swift_proxy] +swift-proxy + +[swift_acc] +swift-storage1 +swift-storage2 +swift-storage3 +swift-storage4 + +[swift_cont] +swift-storage1 +swift-storage2 +swift-storage3 +swift-storage4 + +[swift_obj] +swift-storage1 +swift-storage2 +swift-storage3 +swift-storage4 + +[swift_all:children] +swift_acc +swift_proxy +swift_cont +swift_obj [swift_remote_all] diff --git a/tests/swift_test.conf.j2 b/tests/swift_test.conf.j2 index 2ad3f3de..4ea82719 100644 --- a/tests/swift_test.conf.j2 +++ b/tests/swift_test.conf.j2 @@ -8,7 +8,7 @@ # For keystone v2 change auth_version to 2 and auth_prefix to /v2.0/ # And "allow_account_management" should not be set "true" auth_version = 3 -auth_host = 10.100.100.2 +auth_host = {{ internal_lb_vip_address }} auth_port = 5000 auth_ssl = no auth_prefix = /v3/ diff --git a/tests/test-install-infra.yml b/tests/test-install-infra.yml new file mode 100644 index 00000000..79ef1bd0 --- /dev/null +++ b/tests/test-install-infra.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2015, Rackspace US, 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: Playbook for deploying infra services + hosts: service_all + user: root + gather_facts: true + roles: + - role: "memcached_server" + - role: "galera_server" + vars_files: + - test-vars.yml diff --git a/tests/test-install-keystone.yml b/tests/test-install-keystone.yml new file mode 100644 index 00000000..4c5c8c4f --- /dev/null +++ b/tests/test-install-keystone.yml @@ -0,0 +1,52 @@ +--- +# Copyright 2015, Rackspace US, 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: Playbook for deploying keystone + hosts: keystone_all + user: root + gather_facts: true + pre_tasks: + - name: Create DB for service + mysql_db: + login_user: "root" + login_password: "secrete" + login_host: "localhost" + name: "{{ keystone_galera_database }}" + state: "present" + delegate_to: "{{ groups['galera_all'][0] }}" + when: inventory_hostname == groups['keystone_all'][0] + tags: + - mysql-db-setup + - name: Grant access to the DB for the service + mysql_user: + login_user: "{{ galera_root_user }}" + login_password: "{{ galera_root_password }}" + login_host: "localhost" + name: "{{ keystone_galera_database }}" + password: "{{ keystone_container_mysql_password }}" + host: "{{ item }}" + state: "present" + priv: "{{ keystone_galera_database }}.*:ALL" + with_items: + - "localhost" + - "%" + delegate_to: "{{ groups['galera_all'][0] }}" + when: inventory_hostname == groups['keystone_all'][0] + tags: + - mysql-db-setup + roles: + - role: os_keystone + vars_files: + - test-vars.yml diff --git a/tests/test-install-swift.yml b/tests/test-install-swift.yml new file mode 100644 index 00000000..8cdb6551 --- /dev/null +++ b/tests/test-install-swift.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2015, Rackspace US, 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: Playbook for deploying swift + hosts: swift_all + user: root + gather_facts: true + pre_tasks: + - name: Set swift replication address (container) + set_fact: + replication_address: "{{ hostvars[inventory_hostname]['container_networks']['replication_address']['address'] }}" + when: + - inventory_hostname in groups['swift_all'] + - hostvars[inventory_hostname]['container_networks']['replication_address']['address'] is defined + roles: + - role: "{{ rolename | basename }}" + vars_files: + - test-vars.yml diff --git a/tests/test-prepare-containers.yml b/tests/test-prepare-containers.yml new file mode 100644 index 00000000..c0d539ea --- /dev/null +++ b/tests/test-prepare-containers.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2015, Rackspace US, 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: Playbook for creating containers + hosts: all_containers + gather_facts: false + roles: + - role: "lxc_container_create" + lxc_container_release: trusty + lxc_container_backing_store: dir + global_environment_variables: + PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + post_tasks: + - name: Wait for ssh to be available + local_action: + module: wait_for + port: "{{ ansible_ssh_port | default('22') }}" + host: "{{ ansible_ssh_host | default(inventory_hostname) }}" + search_regex: OpenSSH + delay: 1 diff --git a/tests/test-prepare-host.yml b/tests/test-prepare-host.yml new file mode 100644 index 00000000..a1fb8581 --- /dev/null +++ b/tests/test-prepare-host.yml @@ -0,0 +1,62 @@ +--- +# Copyright 2015, Rackspace US, 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: Playbook for configuring the LXC host + hosts: localhost + pre_tasks: + - name: Update apt cache + apt: + update_cache: yes + when: ansible_os_family == 'Debian' + - name: Ensure root's new public ssh key is in authorized_keys + authorized_key: + user: root + key: "{{ hostvars['localhost']['lxc_container_ssh_key'] }}" + manage_dir: no + - set_fact: + lxc_container_ssh_key: "{{ hostvars['localhost']['lxc_container_ssh_key'] }}" + - name: Check if this is an OpenStack-CI nodepool instance + stat: + path: /etc/nodepool/provider + register: nodepool + - name: Set the files to copy into the container cache for OpenStack-CI instances + set_fact: + lxc_container_cache_files: + - { src: '/etc/pip.conf', dest: '/etc/pip.conf' } + - { src: '/etc/apt/apt.conf.d/99unauthenticated', dest: '/etc/apt/apt.conf.d/99unauthenticated' } + when: nodepool.stat.exists | bool + - name: Determine the existing Ubuntu repo configuration + shell: 'awk "/^deb .*ubuntu\/? {{ ansible_distribution_release }} main/ {print \$2; exit}" /etc/apt/sources.list' + register: ubuntu_repo + changed_when: false + - name: Set apt repo facts based on discovered information + set_fact: + lxc_container_template_main_apt_repo: "{{ ubuntu_repo.stdout }}" + lxc_container_template_security_apt_rep: "{{ ubuntu_repo.stdout }}" + post_tasks: + - name: Create br-storage bridge + shell: /sbin/brctl addbr br-storage || true + - name: IP br-storage + command: /sbin/ifconfig br-storage 10.100.101.1 netmask 255.255.255.0 + - name: Create br-repl bridge + shell: /sbin/brctl addbr br-repl || true + - name: IP br-repl + command: /sbin/ifconfig br-repl 10.100.102.1 netmask 255.255.255.0 + - name: Add iptables rule to ensure ssh checksum is correct + command: /sbin/iptables -A POSTROUTING -t mangle -p tcp --dport 22 -j CHECKSUM --checksum-fill + roles: + - role: "lxc_hosts" + vars_files: + - test-vars.yml diff --git a/tests/test-prepare-keys.yml b/tests/test-prepare-keys.yml new file mode 100644 index 00000000..a4fad4f5 --- /dev/null +++ b/tests/test-prepare-keys.yml @@ -0,0 +1,33 @@ +--- +# Copyright 2015, Rackspace US, 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. + +# NOTE: we use become_user because setting become: no or become: false +# doesn't seem to override the ansible_become=true in the +# inventory +- name: Playbook for establishing ssh keys + hosts: localhost + become_user: "{{ ansible_ssh_user }}" + pre_tasks: + - name: Create ssh key pair for root + user: + name: "{{ ansible_ssh_user }}" + generate_ssh_key: "yes" + ssh_key_bits: 2048 + ssh_key_file: ".ssh/id_rsa" + - name: Get the calling user's key + command: cat ~/.ssh/id_rsa.pub + register: key_get + - set_fact: + lxc_container_ssh_key: "{{ key_get.stdout }}" diff --git a/tests/test-setup-swifthosts.yml b/tests/test-setup-swifthosts.yml new file mode 100644 index 00000000..b02dcb81 --- /dev/null +++ b/tests/test-setup-swifthosts.yml @@ -0,0 +1,86 @@ +--- +# Copyright 2015, Rackspace US, 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: Swift setup + hosts: swift_hosts + user: root + gather_facts: true + pre_tasks: + - name: Ensure xfsprogs is installed on localhost + apt: + name: xfsprogs + state: present + delegate_to: "{{ physical_host }}" + run_once: true + - name: Ensure xfsprogs is installed on containers + apt: + name: xfsprogs + state: present + - name: Openstack directory Create + file: + state: directory + path: "/openstack/{{ item }}" + with_items: + - 'swift1' + - 'swift2' + - name: Create sparse Swift files + shell: "truncate -s 1024G /opt/{{container_name}}_{{ item }}.img" + args: + creates: "/opt/{{ container_name}}_{{ item }}.img" + with_items: + - 'swift1' + - 'swift2' + register: swift_create + delegate_to: "{{ physical_host }}" + - name: Format the Swift files + filesystem: + fstype: xfs + dev: "/opt/{{ container_name}}_{{ item }}.img" + when: swift_create | changed + with_items: + - 'swift1' + - 'swift2' + delegate_to: "{{ physical_host }}" + - name: Create the Swift fstab entries and mount the file systems + mount: + name: "/srv/{{ container_name }}_{{ item }}" + src: "/opt/{{ container_name }}_{{ item }}.img" + fstype: xfs + opts: 'loop,noatime,nodiratime,nobarrier,logbufs=8' + passno: 0 + dump: 0 + state: mounted + with_items: + - 'swift1' + - 'swift2' + register: mount_status + until: mount_status | success + retries: 5 + delay: 2 + delegate_to: "{{ physical_host }}" + - name: Swift extra lxc config + lxc_container: + name: "{{ container_name }}" + container_config: + - "lxc.mount.entry=/srv/{{ container_name }}_swift1 openstack/swift1 none bind 0 0" + - "lxc.mount.entry=/srv/{{ container_name }}_swift2 openstack/swift2 none bind 0 0" + delegate_to: "{{ physical_host }}" + - name: Wait for ssh to be available + local_action: + module: wait_for + port: "{{ ansible_ssh_port | default('22') }}" + host: "{{ ansible_ssh_host | default(inventory_hostname) }}" + search_regex: OpenSSH + delay: 1 diff --git a/tests/test-swift-functional.yml b/tests/test-swift-functional.yml new file mode 100644 index 00000000..f6b210ea --- /dev/null +++ b/tests/test-swift-functional.yml @@ -0,0 +1,120 @@ + + +- name: Setup testing - run Swift functional tests + hosts: swift_proxy[0] + user: root + gather_facts: true + pre_tasks: + - name: Ensure test projects + keystone: + command: "ensure_tenant" + endpoint: "{{ keystone_service_adminurl }}" + login_user: "{{ keystone_admin_user_name }}" + login_password: "{{ keystone_auth_admin_password }}" + login_project_name: "{{ keystone_admin_tenant_name }}" + description: "Testing tenant" + tenant_name: "{{item.project_name }}" + domain_name: "{{ item.domain_name }}" + insecure: "{{ keystone_service_adminuri_insecure }}" + with_items: + - { project_name: "test1", domain_name: "Default" } + - { project_name: "test2", domain_name: "Default" } + - { project_name: "test5", domain_name: "Default" } + - { project_name: "test6", domain_name: "Default" } + register: add_service + run_once: true + until: add_service|success + retries: 5 + delay: 10 + - name: Ensure required roles + keystone: + command: "ensure_role" + endpoint: "{{ keystone_service_adminurl }}" + login_user: "{{ keystone_admin_user_name }}" + login_password: "{{ keystone_auth_admin_password }}" + login_project_name: "{{ keystone_admin_tenant_name }}" + role_name: "{{ item }}" + insecure: "{{ keystone_service_adminuri_insecure }}" + with_items: + - "ResellerAdmin" + - "test-role" + - "test5" + run_once: true + register: add_service + until: add_service|success + retries: 5 + delay: 10 + - name: Add swift users for testing + keystone: + command: "ensure_user" + endpoint: "{{ keystone_service_adminurl }}" + login_user: "{{ keystone_admin_user_name }}" + login_password: "{{ keystone_auth_admin_password }}" + login_project_name: "{{ keystone_admin_tenant_name }}" + user_name: "{{ item.user_name }}" + project_name: "{{ item.project_name }}" + domain_name: "{{ item.domain_name }}" + password: "{{ item.password }}" + insecure: "{{ keystone_service_adminuri_insecure }}" + with_items: + - { user_name: "test1", project_name: "test1", password: "test1", domain_name: "Default" } + - { user_name: "test2", project_name: "test2", password: "test2", domain_name: "Default" } + - { user_name: "test3", project_name: "test1", password: "test3", domain_name: "Default" } + - { user_name: "test5", project_name: "test5", password: "test5", domain_name: "Default" } + - { user_name: "test6", project_name: "test6", password: "test6", domain_name: "Default" } + run_once: true + register: add_service + until: add_service|success + retries: 5 + delay: 10 + - name: Ensure roles for swift test users + keystone: + command: "ensure_user_role" + endpoint: "{{ keystone_service_adminurl }}" + login_user: "{{ keystone_admin_user_name }}" + login_password: "{{ keystone_auth_admin_password }}" + login_project_name: "{{ keystone_admin_tenant_name }}" + user_name: "{{ item.user_name }}" + domain_name: "{{ item.domain_name }}" + project_name: "{{ item.project_name }}" + role_name: "{{ item.role_name }}" + insecure: "{{ keystone_service_adminuri_insecure }}" + with_items: + - { user_name: "test1", project_name: "test1", role_name: "admin", domain_name: "Default" } + - { user_name: "test2", project_name: "test2", role_name: "admin", domain_name: "Default" } + - { user_name: "test3", project_name: "test1", role_name: "test-role", domain_name: "Default" } + - { user_name: "test5", project_name: "test5", role_name: "test5", domain_name: "Default" } + - { user_name: "test6", project_name: "test6", role_name: "ResellerAdmin", domain_name: "Default" } + retries: 5 + run_once: true + register: add_service + until: add_service|success + retries: 5 + delay: 10 + - name: Clone swift repository on proxy-host + git: + repo: "https://git.openstack.org/openstack/swift" + dest: "/opt/swift" + update: yes + clone: yes + version: master + - name: Install requirements for swift + pip: + requirements: "{{ item }}" + virtualenv: "{{ swift_venv_bin | dirname }}" + with_items: + - "/opt/swift/test-requirements.txt" + - "/opt/swift/requirements.txt" + - name: Setup test.conf for testing + template: + src: "swift_test.conf.j2" + dest: "/etc/swift/test.conf" + owner: "swift" + group: "swift" + - name: Run functional tests for swift + shell: "source /openstack/venvs/swift-untagged/bin/activate && ./.functests" + args: + chdir: "/opt/swift/" + executable: "/bin/bash" + vars_files: + - test-vars.yml diff --git a/tests/test-vars.yml b/tests/test-vars.yml new file mode 100644 index 00000000..e22b38a3 --- /dev/null +++ b/tests/test-vars.yml @@ -0,0 +1,104 @@ +--- +# Copyright 2015, Rackspace US, 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. + +# General Environment Settings +external_lb_vip_address: 10.100.100.101 +internal_lb_vip_address: 10.100.100.101 +debug: true +verbose: true + +# LXC Settings +lxc_net_address: 10.100.100.1 +lxc_net_netmask: 255.255.255.0 +lxc_net_dhcp_range: 10.100.100.2,10.100.100.99 +lxc_net_bridge: lxcbr0 +lxc_kernel_options: + - { key: 'fs.inotify.max_user_instances', value: 1024 } + +# Galera Settings +galera_root_password: secrete +galera_root_user: root +galera_innodb_buffer_pool_size: 512M +galera_innodb_log_buffer_size: 32M +galera_server_id: "{{ inventory_hostname | string_2_int }}" +galera_wsrep_node_name: "{{ inventory_hostname }}" +galera_wsrep_provider_options: + - { option: "gcache.size", value: "32M" } +galera_server_id: "{{ inventory_hostname | string_2_int }}" + +# Memcache Settings +memcached_listen: 10.100.100.101 +memcached_servers: 10.100.100.101 +memcached_encryption_key: "secrete" + +# Keystone Settings +keystone_messaging_enabled: false +keystone_admin_user_name: admin +keystone_admin_tenant_name: admin +keystone_auth_admin_password: "SuperSecretePassword" +keystone_service_adminuri_insecure: false +keystone_service_internaluri_insecure: false +keystone_service_internaluri: "http://{{ internal_lb_vip_address }}:5000" +keystone_service_internalurl: "{{ keystone_service_internaluri }}/v3" +keystone_service_adminuri: "http://{{ internal_lb_vip_address }}:35357" +keystone_service_adminurl: "{{ keystone_service_adminuri }}/v3" +keystone_service_password: "secrete" +keystone_galera_database: keystone +keystone_galera_address: 10.100.100.101 +keystone_container_mysql_password: "SuperSecrete" +keystone_venv_tag: "testing" +keystone_developer_mode: true +keystone_git_install_branch: master +keystone_requirements_git_install_branch: master +keystone_service_region: RegionOne + +# Swift specific settings +swift_storage_address: "{{ ansible_ssh_host }}" +swift_container_mysql_password: "SuperSecrete" +swift_dispersion_password: "secrete" +swift_hash_path_prefix: "secrete_prefx" +swift_hash_path_suffix: "secrete_suffix" +swift_service_password: "secrete" +swift_developer_mode: true +swift_git_install_branch: master +swift_venv_tag: untagged +swift_venv_bin: "/openstack/venvs/swift-{{ swift_venv_tag }}/bin" +swift_service_publicuri: "http://10.100.100.102:8080" +swift_service_adminuri: "http://10.100.100.102:8080" +swift_service_internaluri: "http://10.100.100.102:8080" +swift_replication_address: "{{ replication_address }}" +swift: + storage_network: eth1 + repl_network: eth3 + part_power: 8 + drives: + - name: swift1 + - name: swift2 + mount_point: /openstack + storage_policies: + - policy: + name: gold + index: 0 + repl_number: 3 + default: True +swift_proxy_server_conf_overrides: + "filter:keystoneauth": + reseller_prefix: "AUTH, SERVICE" + "SERVICE_service_roles": "test5" + +# openrc settings +openrc_os_password: "{{ keystone_auth_admin_password }}" +openrc_os_domain_name: "Default" +openrc_os_auth_url: "http://{{ internal_lb_vip_address }}:5000/v3" diff --git a/tests/test.yml b/tests/test.yml index 81bf212b..1773a69a 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -13,472 +13,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -- name: Create keys for container use - hosts: 127.0.0.1 - connection: local - become: false - pre_tasks: - - name: Create ssh key pair for root - user: - name: "{{ ansible_ssh_user }}" - generate_ssh_key: "yes" - ssh_key_bits: 2048 - ssh_key_file: ".ssh/id_rsa" - - name: get the calling users key - command: cat ~/.ssh/id_rsa.pub - register: key_get - - set_fact: - lxc_container_ssh_key: "{{ key_get.stdout }}" +# Prepare the user ssh keys +- include: test-prepare-keys.yml -- name: LXC Host setup - hosts: localhost - connection: local - become: yes - pre_tasks: - # Make sure OS does not have a stale package cache. - - name: Update apt cache. - apt: - update_cache: yes - when: ansible_os_family == 'Debian' - - name: Ensure root's new public ssh key is in authorized_keys - authorized_key: - user: root - key: "{{ hostvars['127.0.0.1']['lxc_container_ssh_key'] }}" - manage_dir: no - - set_fact: - lxc_container_ssh_key: "{{ hostvars['127.0.0.1']['lxc_container_ssh_key'] }}" - - name: Check if this is an OpenStack-CI nodepool instance - stat: - path: /etc/nodepool/provider - register: nodepool - - name: Set the files to copy into the container cache for OpenStack-CI instances - set_fact: - lxc_container_cache_files: - - { src: '/etc/pip.conf', dest: '/etc/pip.conf' } - - { src: '/etc/apt/apt.conf.d/99unauthenticated', dest: '/etc/apt/apt.conf.d/99unauthenticated' } - when: nodepool.stat.exists | bool - - name: Determine the existing Ubuntu repo configuration - shell: 'awk "/^deb .*ubuntu\/? {{ ansible_distribution_release }} main/ {print \$2; exit}" /etc/apt/sources.list' - register: ubuntu_repo - changed_when: false - - name: Set apt repo facts based on discovered information - set_fact: - lxc_container_template_main_apt_repo: "{{ ubuntu_repo.stdout }}" - lxc_container_template_security_apt_rep: "{{ ubuntu_repo.stdout }}" - - name: Ensure xfsprogs is installed - apt: - name: xfsprogs - state: present - roles: - - role: "lxc_hosts" - lxc_net_address: 10.100.100.1 - lxc_net_dhcp_range: 10.100.100.8,10.100.100.253 - lxc_net_bridge: lxcbr0 - lxc_kernel_options: - - { key: 'fs.inotify.max_user_instances', value: 1024 } - lxc_container_caches: - - url: "https://rpc-repo.rackspace.com/container_images/rpc-trusty-container.tgz" - name: "trusty.tgz" - sha256sum: "56c6a6e132ea7d10be2f3e8104f47136ccf408b30e362133f0dc4a0a9adb4d0c" - chroot_path: trusty/rootfs-amd64 - # The $HOME directory is mocked to work with tox - # by defining the 'ansible_env' hash. This should - # NEVER be done outside of testing. - ansible_env: ## NEVER DO THIS OUTSIDE OF TESTING - HOME: "/tmp" - post_tasks: - # Inventory is being pre-loaded using a post tasks instead of through a dynamic - # inventory system. While this is not a usual method for deployment it's being - # done for functional testing. - - name: Create container hosts - add_host: - groups: "all,all_containers,rabbitmq_all,galera_all,service_all,keystone_all" - hostname: "{{ item.name }}" - inventory_hostname: "{{ item.name }}" - ansible_ssh_host: "{{ item.address }}" - ansible_become: true - properties: - service_name: "{{ item.service }}" - container_networks: - management_address: - address: "{{ item.address }}" - bridge: "lxcbr0" - interface: "eth1" - netmask: "255.255.252.0" - type: "veth" - physical_host: localhost - container_name: "{{ item.name }}" - with_items: - - { name: "service1", service: "service1", address: "10.100.100.2" } - - name: Create container hosts - add_host: - groups: "{{ item.groups }}" - hostname: "{{ item.name }}" - inventory_hostname: "{{ item.name }}" - ansible_ssh_host: "{{ item.address }}" - ansible_become: true - properties: - service_name: "{{ item.service }}" - container_networks: - management_address: - address: "{{ item.address }}" - bridge: "lxcbr0" - interface: "eth1" - netmask: "255.255.252.0" - type: "veth" - physical_host: localhost - container_name: "{{ item.name }}" - with_items: - - { name: "swift-proxy", service: "swift", address: "10.100.100.3", groups: "swift_proxy,swift_all,all,all_containers" } - - { name: "swift1", service: "swift", address: "10.100.100.4", groups: "swift_hosts,swift_all,all,all_containers" } - - { name: "swift2", service: "swift", address: "10.100.100.5", groups: "swift_hosts,swift_all,all,all_containers" } - - { name: "swift3", service: "swift", address: "10.100.100.6", groups: "swift_hosts,swift_all,all,all_containers" } - - { name: "swift4", service: "swift", address: "10.100.100.7", groups: "swift_hosts,swift_all,all,all_containers" } +# Prepare the host +- include: test-prepare-host.yml -- name: Create Containers - hosts: all_containers - connection: local - gather_facts: false - roles: - - role: "lxc_container_create" - lxc_container_release: trusty - lxc_container_backing_store: dir - global_environment_variables: - PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - post_tasks: - - name: Wait for ssh to be available - local_action: - module: wait_for - port: "{{ ansible_ssh_port | default('22') }}" - host: "{{ ansible_ssh_host | default(inventory_hostname) }}" - search_regex: OpenSSH - delay: 1 +# Prepare the containers +- include: test-prepare-containers.yml -- name: Setup pre-services - hosts: service_all - user: root - gather_facts: true - roles: - - role: "rabbitmq_server" - rabbitmq_cookie_token: secrete - - role: "galera_server" - galera_root_password: secrete - galera_root_user: root - galera_innodb_buffer_pool_size: 512M - galera_innodb_log_buffer_size: 32M - galera_server_id: "{{ inventory_hostname | string_2_int }}" - galera_wsrep_node_name: "{{ inventory_hostname }}" - galera_wsrep_provider_options: - - { option: "gcache.size", value: "32M" } - galera_server_id: "{{ inventory_hostname | string_2_int }}" - - role: "memcached_server" - memcached_listen: 10.100.100.2 +# Install MariaDB/Memcached +- include: test-install-infra.yml -- name: Setup keystone - hosts: service_all - user: root - gather_facts: true - pre_tasks: - - name: Ensure Rabbitmq vhost - rabbitmq_vhost: - name: "{{ keystone_rabbitmq_vhost }}" - state: "present" - - name: Ensure rabbitmq user - rabbitmq_user: - user: "{{ keystone_rabbitmq_userid }}" - password: "{{ keystone_rabbitmq_password }}" - vhost: "{{ keystone_rabbitmq_vhost }}" - configure_priv: ".*" - read_priv: ".*" - write_priv: ".*" - state: "present" - - name: Create DB for service - mysql_db: - login_user: "root" - login_password: "secrete" - login_host: "localhost" - name: "{{ keystone_galera_database }}" - state: "present" - - name: Grant access to the DB for the service - mysql_user: - login_user: "root" - login_password: "secrete" - login_host: "localhost" - name: "{{ keystone_galera_database }}" - password: "{{ keystone_container_mysql_password }}" - host: "{{ item }}" - state: "present" - priv: "{{ keystone_galera_database }}.*:ALL" - with_items: - - "localhost" - - "%" - roles: - - role: "os_keystone" - vars: - external_lb_vip_address: 10.100.100.2 - internal_lb_vip_address: 10.100.100.2 - keystone_galera_address: 10.100.100.2 - keystone_galera_database: keystone - keystone_venv_tag: "testing" - keystone_developer_mode: true - keystone_git_install_branch: master - keystone_requirements_git_install_branch: master - keystone_auth_admin_token: "SuperSecreteTestToken" - keystone_auth_admin_password: "SuperSecretePassword" - keystone_service_password: "secrete" - keystone_rabbitmq_password: "secrete" - keystone_container_mysql_password: "SuperSecrete" - keystone_rabbitmq_port: 5671 - keystone_rabbitmq_userid: keystone - keystone_rabbitmq_vhost: /keystone - keystone_rabbitmq_servers: 10.100.100.2 - keystone_rabbitmq_use_ssl: false - galera_client_drop_config_file: false +# Install Keystone +- include: test-install-keystone.yml -- name: Swift setup - hosts: swift_hosts - user: root - gather_facts: true - pre_tasks: - - name: Ensure xfsprogs is installed - apt: - name: xfsprogs - state: present - - name: Openstack directory Create - file: - state: directory - path: "/openstack/{{ item }}" - with_items: - - 'swift1' - - 'swift2' - - name: Create sparse Swift files - shell: "truncate -s 1024G /opt/{{container_name}}_{{ item }}.img" - args: - creates: "/opt/{{ container_name}}_{{ item }}.img" - with_items: - - 'swift1' - - 'swift2' - register: swift_create - delegate_to: "{{ physical_host }}" - - name: Format the Swift files - filesystem: - fstype: xfs - dev: "/opt/{{ container_name}}_{{ item }}.img" - when: swift_create | changed - with_items: - - 'swift1' - - 'swift2' - delegate_to: "{{ physical_host }}" - - name: Create the Swift fstab entries and mount the file systems - mount: - name: "/srv/{{ container_name }}_{{ item }}" - src: "/opt/{{ container_name }}_{{ item }}.img" - fstype: xfs - opts: 'loop,noatime,nodiratime,nobarrier,logbufs=8' - passno: 0 - dump: 0 - state: mounted - with_items: - - 'swift1' - - 'swift2' - register: mount_status - until: mount_status | success - retries: 5 - delay: 2 - delegate_to: "{{ physical_host }}" - - name: Swift extra lxc config - lxc_container: - name: "{{ container_name }}" - container_config: - - "lxc.mount.entry=/srv/{{ container_name }}_swift1 openstack/swift1 none bind 0 0" - - "lxc.mount.entry=/srv/{{ container_name }}_swift2 openstack/swift2 none bind 0 0" - delegate_to: "{{ physical_host }}" - - name: Wait for ssh to be available - local_action: - module: wait_for - port: "{{ ansible_ssh_port | default('22') }}" - host: "{{ ansible_ssh_host | default(inventory_hostname) }}" - search_regex: OpenSSH - delay: 1 +# Setup Swift hosts +- include: test-setup-swifthosts.yml -- name: Playbook for deploying swift - hosts: swift_all - user: root - gather_facts: true - roles: - - role: "{{ rolename | basename }}" - vars: - swift: - storage_network: eth1 - part_power: 8 - drives: - - name: swift1 - - name: swift2 - mount_point: /openstack - storage_policies: - - policy: - name: gold - index: 0 - repl_number: 3 - default: True - swift_proxy_server_conf_overrides: - "filter:keystoneauth": - reseller_prefix: "AUTH, SERVICE" - "SERVICE_service_roles": "test5" - memcached_servers: 10.100.100.2 - external_lb_vip_address: 10.100.100.3 - internal_lb_vip_address: 10.100.100.3 - swift_storage_address: "{{ ansible_ssh_host }}" - swift_container_mysql_password: "SuperSecrete" - swift_dispersion_password: "secrete" - swift_hash_path_prefix: "secrete_prefx" - swift_hash_path_suffix: "secrete_suffix" - swift_service_password: "secrete" - swift_developer_mode: true - keystone_admin_user_name: admin - keystone_admin_tenant_name: admin - keystone_auth_admin_password: "SuperSecretePassword" - keystone_service_adminuri_insecure: false - keystone_service_internaluri_insecure: false - keystone_service_internaluri: "http://10.100.100.2:5000" - keystone_service_internalurl: "{{ keystone_service_internaluri }}/v3" - keystone_service_adminuri: "http://10.100.100.2:35357" - keystone_service_adminurl: "{{ keystone_service_adminuri }}/v3" - swift_git_install_branch: master - openrc_os_password: "{{ keystone_auth_admin_password }}" - openrc_os_domain_name: "Default" - openrc_os_auth_url: "http://10.100.100.2:5000/v3" - memcached_encryption_key: "secrete" - debug: true - verbose: true +# Install Swift +- include: test-install-swift.yml -- name: Setup testing - run Swift functional tests - hosts: swift_proxy[0] - user: root - gather_facts: true - pre_tasks: - - name: Ensure test projects - keystone: - command: "ensure_tenant" - endpoint: "{{ keystone_service_adminurl }}" - login_user: "{{ keystone_admin_user_name }}" - login_password: "{{ keystone_auth_admin_password }}" - login_project_name: "{{ keystone_admin_tenant_name }}" - description: "Testing tenant" - tenant_name: "{{item.project_name }}" - domain_name: "{{ item.domain_name }}" - insecure: "{{ keystone_service_adminuri_insecure }}" - with_items: - - { project_name: "test1", domain_name: "Default" } - - { project_name: "test2", domain_name: "Default" } - - { project_name: "test5", domain_name: "Default" } - - { project_name: "test6", domain_name: "Default" } - register: add_service - run_once: true - until: add_service|success - retries: 5 - delay: 10 - - name: Ensure required roles - keystone: - command: "ensure_role" - endpoint: "{{ keystone_service_adminurl }}" - login_user: "{{ keystone_admin_user_name }}" - login_password: "{{ keystone_auth_admin_password }}" - login_project_name: "{{ keystone_admin_tenant_name }}" - role_name: "{{ item }}" - insecure: "{{ keystone_service_adminuri_insecure }}" - with_items: - - "ResellerAdmin" - - "test-role" - - "test5" - run_once: true - register: add_service - until: add_service|success - retries: 5 - delay: 10 - - name: Add swift users for testing - keystone: - command: "ensure_user" - endpoint: "{{ keystone_service_adminurl }}" - login_user: "{{ keystone_admin_user_name }}" - login_password: "{{ keystone_auth_admin_password }}" - login_project_name: "{{ keystone_admin_tenant_name }}" - user_name: "{{ item.user_name }}" - project_name: "{{ item.project_name }}" - domain_name: "{{ item.domain_name }}" - password: "{{ item.password }}" - insecure: "{{ keystone_service_adminuri_insecure }}" - with_items: - - { user_name: "test1", project_name: "test1", password: "test1", domain_name: "Default" } - - { user_name: "test2", project_name: "test2", password: "test2", domain_name: "Default" } - - { user_name: "test3", project_name: "test1", password: "test3", domain_name: "Default" } - - { user_name: "test5", project_name: "test5", password: "test5", domain_name: "Default" } - - { user_name: "test6", project_name: "test6", password: "test6", domain_name: "Default" } - run_once: true - register: add_service - until: add_service|success - retries: 5 - delay: 10 - - name: Ensure roles for swift test users - keystone: - command: "ensure_user_role" - endpoint: "{{ keystone_service_adminurl }}" - login_user: "{{ keystone_admin_user_name }}" - login_password: "{{ keystone_auth_admin_password }}" - login_project_name: "{{ keystone_admin_tenant_name }}" - user_name: "{{ item.user_name }}" - domain_name: "{{ item.domain_name }}" - project_name: "{{ item.project_name }}" - role_name: "{{ item.role_name }}" - insecure: "{{ keystone_service_adminuri_insecure }}" - with_items: - - { user_name: "test1", project_name: "test1", role_name: "admin", domain_name: "Default" } - - { user_name: "test2", project_name: "test2", role_name: "admin", domain_name: "Default" } - - { user_name: "test3", project_name: "test1", role_name: "test-role", domain_name: "Default" } - - { user_name: "test5", project_name: "test5", role_name: "test5", domain_name: "Default" } - - { user_name: "test6", project_name: "test6", role_name: "ResellerAdmin", domain_name: "Default" } - retries: 5 - run_once: true - register: add_service - until: add_service|success - retries: 5 - delay: 10 - - name: Clone swift repository on proxy-host - git: - repo: "https://git.openstack.org/openstack/swift" - dest: "/opt/swift" - update: yes - clone: yes - version: master - - name: Install requirements for swift - pip: - requirements: "{{ item }}" - virtualenv: "{{ swift_venv_bin | dirname }}" - with_items: - - "/opt/swift/test-requirements.txt" - - "/opt/swift/requirements.txt" - - name: Setup test.conf for testing - template: - src: "swift_test.conf.j2" - dest: "/etc/swift/test.conf" - owner: "swift" - group: "swift" - - name: Run functional tests for swift - shell: "source /openstack/venvs/swift-untagged/bin/activate && ./.functests" - args: - chdir: "/opt/swift/" - executable: "/bin/bash" - vars: - keystone_admin_user_name: admin - keystone_admin_tenant_name: admin - keystone_auth_admin_password: "SuperSecretePassword" - keystone_service_adminuri_insecure: false - keystone_service_internaluri_insecure: false - keystone_service_internaluri: "http://10.100.100.2:5000" - keystone_service_internalurl: "{{ keystone_service_internaluri }}/v3" - keystone_service_adminuri: "http://10.100.100.2:35357" - keystone_service_adminurl: "{{ keystone_service_adminuri }}/v3" - swift_venv_tag: untagged - swift_venv_bin: "/openstack/venvs/swift-{{ swift_venv_tag }}/bin" - debug: true - verbose: true +# Test Swift +- include: test-swift-functional.yml