feat: Add keycloak (#510)
* feat: Add keycloak
* fix lint error
* Deploy keycloak in default
* Fix role names in deps
* Remove dynamic key in ansible variable dic
* Use custom wait logic because postgresql CRD doesn't have condition status
* Use production mode for keycloak
* Wait until zalando operator ready
* Set admin password explicitly
* Fix ingress config
* Create grafana client in keycloak and enable oauth in grafana
* Use PXC instead of zalando postgres
* Set default value for atmosphere_keycloak_enabled
* Split the mysql queries into multiple parts
* Solve convo
* Use ansible module for keycloak realm
* Concatenate realm arrays
* Tune keycloak config to work with mysql vendor and fix keycloak db user's host config
* Add notes about mysql vendor support in keycloak
* remove default client scope setting
it requires community.general collection upgrade to 4.7.0.
But there are other collections in the deps list which use lower versions.
Need to bump its version at some time surely.
* Tuen grafana oauth config
* Fix keycloak client auth mode
* Use a variable for keycloak database name
* Fix lint error
* Remove unused var from doc
* Manage pxc strict mode in ansible
* revert the changes out of the scope
* ignore changes during realm creation
* Resolve commnents
* Fix default values
* Use official keycloak image instead of bitnami
* Set proxy mode using KC env var
* securely reference oauth secrets in grafana.ini
* Remove implicit octal value in helm values
* Support id token in keycloak clients for rbac and add ingress role
* Update grafana role map attribute
* Use j2 template
https://stackoverflow.com/questions/63961938/ansible-variable-conversion-to-int-is-ignored
* Create client roles
* Fix yaml lint error
* Add keycloak health check in consumer roles
* fix: use correct annotations
* chore: add keystone-keycloak-backend to keystone
* fix: make openstack_helm_endpoints work cleaner
* chore: clean up unecessary docs
* fix: lock down grafana to allow users with roles only
* feat: integrate keystone with keycloak
* chore: added horizon auth via keycloak
* chore: add slo for grafana
* chore: bump to 0.1.5
* Fix yaml lint error
* Fix client role creation
* chore(kube-prometheus-stack): update to latest
* fix: KubeJobFailed should be SEV-3
* chore: refactor softnet alerts
* chore(monitoring): migrate to using jsonnet
* chore: refactor alerts
* chore: major monitoring refactor
* fix: solve alerts
* fix: apiserver selector
* more cleanups
* switch from SEV- to P
* fix: improve port binding alerts
* fix admin state alert for neutron
* map some more alerts
* drop uuid
* Revert "drop uuid"
This reverts commit ad0f05d0e7564759e8259c2cc53c2e2f5c73e1b8.
* fix: drop recording rules
* switch alertmanager to jsonnet
* fix: idempotence for monitoring
* chore: fix linters
* chore: lower ceph osd timeouts to p4
* chore: refactor to using new jsonnet
* chore: use vendor path
* chore: fix mixin for alertmanager
* core: fix selector
* ci: add initial keycloak kind tests
* ci: run keycloak basic scenario
* chore: refactor to using multiple domains
* chore: wip for keycloak multidomain
* adding multi domain support for keycloak as external identity provider (#556)
Co-authored-by: Mohammed Naser <mnaser@vexxhost.com>
* chore: initial impl for multiple domain
* chore: grafan + keycloak wip
* chore: fix missing roles
* chore: remove commented out role
* chore: add ci debug
* chore: use smaller nodes for test
* ci: fix keycloak_user_info
* ci: fix keycloak_user_info
* ci: debug keycloak ci
* chore: fix linters
* ci: retry a few times for keycloak users to appear
* ci: ci fixes
* ci: misc fixes
* ci: fix secret generation
* ci: fix missing secrets
---------
Co-authored-by: okozachenko1203 <okozachenko1203@users.noreply.github.com>
Co-authored-by: Mohammed Naser <mnaser@vexxhost.com>
Co-authored-by: Jeremy Lee <6729613+legit-ninja@users.noreply.github.com>
diff --git a/molecule/csi/cleanup.yml b/molecule/csi/cleanup.yml
index 45d16dc..06dd8c4 100644
--- a/molecule/csi/cleanup.yml
+++ b/molecule/csi/cleanup.yml
@@ -12,4 +12,4 @@
# License for the specific language governing permissions and limitations
# under the License.
-- ansible.builtin.import_playbook: vexxhost.ceph.destroy_fake_devices
+- ansible.builtin.import_playbook: ../shared/cleanup/ceph.yml
diff --git a/molecule/csi/converge.yml b/molecule/csi/converge.yml
index 074266a..4f54b15 100644
--- a/molecule/csi/converge.yml
+++ b/molecule/csi/converge.yml
@@ -12,8 +12,4 @@
# License for the specific language governing permissions and limitations
# under the License.
-- ansible.builtin.import_playbook: vexxhost.ceph.site
- when: csi_driver == "rbd"
-
-- ansible.builtin.import_playbook: vexxhost.atmosphere.kubernetes
- ansible.builtin.import_playbook: vexxhost.atmosphere.csi
diff --git a/molecule/csi/molecule.yml b/molecule/csi/molecule.yml
deleted file mode 100644
index a1cdf53..0000000
--- a/molecule/csi/molecule.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (c) 2023 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.
-
-dependency:
- name: galaxy
-driver:
- name: docker
-platforms:
- - name: instance
- image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2004}-ansible:latest
- command: ${MOLECULE_DOCKER_COMMAND:-""}
- privileged: true
- cgroupns_mode: host
- pre_build_image: true
- etc_hosts:
- k8s: 172.17.0.100
- environment:
- container: docker
- security_opts:
- - apparmor=unconfined
- volumes:
- - /dev:/dev
- - /lib/modules:/lib/modules:ro
- - /sys/fs/cgroup:/sys/fs/cgroup:rw
- - /usr/src:/usr/src:ro
- groups:
- - controllers
- - cephs
-provisioner:
- name: ansible
- config_options:
- connection:
- pipelining: true
- tags:
- skip: sysctl,ethtool
- inventory:
- group_vars:
- all:
- ceph_fsid: ${MOLECULE_CEPH_FSID:-"1dff0e0f-3c44-48da-81cd-4f3c6e8722b2"}
- ceph_conf_overrides:
- - section: global
- option: osd crush chooseleaf type
- value: 0
- - section: mon
- option: auth allow insecure global id reclaim
- value: false
- cilium_helm_values:
- operator:
- replicas: 1
- csi_driver: ${MOLECULE_CSI_DRIVER:-"rbd"}
- ceph_csi_rbd_helm_values:
- provisioner:
- replicaCount: 1
- controllers:
- kubernetes_keepalived_interface: "{{ ansible_default_ipv4.interface }}"
- kubernetes_keepalived_vip: 172.17.0.100
- kubernetes_keepalived_vrid: 42
- kubernetes_hostname: k8s
- cephs:
- ceph_osd_devices:
- - "/dev/ceph-{{ inventory_hostname_short }}-osd0/data"
- - "/dev/ceph-{{ inventory_hostname_short }}-osd1/data"
- - "/dev/ceph-{{ inventory_hostname_short }}-osd2/data"
-verifier:
- name: ansible
diff --git a/molecule/csi/molecule.yml b/molecule/csi/molecule.yml
new file mode 120000
index 0000000..6446c65
--- /dev/null
+++ b/molecule/csi/molecule.yml
@@ -0,0 +1 @@
+../shared/molecule.yml
\ No newline at end of file
diff --git a/molecule/csi/prepare.yml b/molecule/csi/prepare.yml
index dac0bc4..d922e73 100644
--- a/molecule/csi/prepare.yml
+++ b/molecule/csi/prepare.yml
@@ -12,36 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-- name: Prepare
- hosts: all
- become: true
- pre_tasks:
- - name: Wait for systemd to complete initialization
- ansible.builtin.command: systemctl is-system-running
- register: systemctl_status
- until: >
- 'running' in systemctl_status.stdout or
- 'degraded' in systemctl_status.stdout
- retries: 30
- delay: 5
- changed_when: false
- failed_when: systemctl_status.rc > 1
- tasks:
- - name: Refresh cache
- ansible.builtin.package:
- update_cache: true
-
- # NOTE(mnaser): The base image installs Ansible using `pip` which breaks
- # the system Python, we uninstall all Python packages.
- - name: Fix Python installation
- block:
- - name: Get all Python packages
- ansible.builtin.command: pip freeze
- register: pip_freeze
-
- - name: Uninstall all Python packages
- ansible.builtin.pip:
- name: "{{ pip_freeze.stdout_lines }}"
- state: absent
-
-- ansible.builtin.import_playbook: vexxhost.ceph.create_fake_devices
+- ansible.builtin.import_playbook: ../shared/prepare/base.yml
+- ansible.builtin.import_playbook: ../shared/prepare/ceph.yml
+- ansible.builtin.import_playbook: ../shared/prepare/kubernetes.yml
diff --git a/molecule/keycloak/converge.yml b/molecule/keycloak/converge.yml
new file mode 100644
index 0000000..2a2fd38
--- /dev/null
+++ b/molecule/keycloak/converge.yml
@@ -0,0 +1,21 @@
+# Copyright (c) 2023 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
+ become: true
+ roles:
+ - vexxhost.atmosphere.keycloak
+ - vexxhost.atmosphere.kube_prometheus_stack
+ - vexxhost.atmosphere.keystone
+ - vexxhost.atmosphere.horizon
diff --git a/molecule/keycloak/molecule.yml b/molecule/keycloak/molecule.yml
new file mode 120000
index 0000000..6446c65
--- /dev/null
+++ b/molecule/keycloak/molecule.yml
@@ -0,0 +1 @@
+../shared/molecule.yml
\ No newline at end of file
diff --git a/molecule/keycloak/prepare.yml b/molecule/keycloak/prepare.yml
new file mode 100644
index 0000000..b94b2ed
--- /dev/null
+++ b/molecule/keycloak/prepare.yml
@@ -0,0 +1,27 @@
+# Copyright (c) 2023 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: ../shared/prepare/base.yml
+- import_playbook: ../shared/prepare/kubernetes.yml
+
+- hosts: controllers
+ become: true
+ roles:
+ - vexxhost.atmosphere.cert_manager
+ - vexxhost.atmosphere.cluster_issuer
+ - vexxhost.atmosphere.ingress_nginx
+ - vexxhost.atmosphere.rabbitmq_cluster_operator
+ - vexxhost.atmosphere.percona_xtradb_cluster_operator
+ - vexxhost.atmosphere.percona_xtradb_cluster
+ - vexxhost.atmosphere.memcached
diff --git a/molecule/keycloak/verify.yml b/molecule/keycloak/verify.yml
new file mode 100644
index 0000000..578e1cc
--- /dev/null
+++ b/molecule/keycloak/verify.yml
@@ -0,0 +1,62 @@
+# Copyright (c) 2023 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: Create user and assert it exists inside Keystone
+ hosts: all
+ tasks:
+ - name: Create Keycloak user
+ run_once: true
+ delegate_to: localhost
+ community.general.keycloak_user:
+ # Keycloak settings
+ auth_keycloak_url: "https://{{ keycloak_host }}"
+ auth_realm: master
+ auth_client_id: admin-cli
+ auth_username: admin
+ auth_password: "{{ keycloak_admin_password }}"
+ validate_certs: "{{ cluster_issuer_type != 'self-signed' }}"
+ # User settings
+ realm: atmosphere
+ username: test-user
+ register: keycloak_user_result
+
+ - name: Set a fact with user information using "end_state" or "existing"
+ run_once: true
+ ansible.builtin.set_fact:
+ keycloak_user_info: "{{ keycloak_user_result.existing | ternary(keycloak_user_result.existing, keycloak_user_result.end_state) }}"
+
+ - name: Get list of all users in "atmosphere" domain
+ run_once: true
+ delegate_to: localhost
+ vexxhost.atmosphere.identity_user_info:
+ domain: atmosphere
+ name: "{{ keycloak_user_info.username }}"
+ register: identity_user_info_result
+ # XXX(mnaser): GHA seems to be slow so the user doesn't show up right
+ # away, it could also be a Keystone caching issue, for now
+ # we try a few more times.
+ retries: 30
+ delay: 1
+ until: identity_user_info_result.openstack_users | length > 0
+
+ - name: Assert that the user exists
+ run_once: true
+ ansible.builtin.assert:
+ that:
+ - identity_user_info_result.openstack_users | length > 0
+ - identity_user_info_result.openstack_users[0].id == keycloak_user_info.id
+ - identity_user_info_result.openstack_users[0].name == keycloak_user_info.username
+
+ # TODO: Simulate Keystone authentication
+ # TODO: Simulate Horizon login
diff --git a/molecule/shared/cleanup/ceph.yml b/molecule/shared/cleanup/ceph.yml
new file mode 100644
index 0000000..45d16dc
--- /dev/null
+++ b/molecule/shared/cleanup/ceph.yml
@@ -0,0 +1,15 @@
+# Copyright (c) 2023 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.
+
+- ansible.builtin.import_playbook: vexxhost.ceph.destroy_fake_devices
diff --git a/molecule/shared/molecule.yml b/molecule/shared/molecule.yml
new file mode 100644
index 0000000..11bb81f
--- /dev/null
+++ b/molecule/shared/molecule.yml
@@ -0,0 +1,153 @@
+# Copyright (c) 2023 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.
+
+dependency:
+ name: galaxy
+driver:
+ name: docker
+platforms:
+ - name: ${MOLECULE_SCENARIO_NAME}
+ image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2004}-ansible:latest
+ command: ${MOLECULE_DOCKER_COMMAND:-""}
+ privileged: true
+ cgroupns_mode: host
+ pre_build_image: true
+ purge_networks: true
+ dns_servers:
+ - 1.1.1.1
+ docker_networks:
+ - name: mgmt
+ ipam_config:
+ - subnet: 10.96.240.0/24
+ gateway: 10.96.240.1
+ - name: public
+ ipam_config:
+ - subnet: 10.96.250.0/24
+ gateway: 10.96.250.1
+ networks:
+ - name: mgmt
+ - name: public
+ published_ports:
+ - 80:80
+ - 443:443
+ security_opts:
+ - apparmor=unconfined
+ volumes:
+ - /dev:/dev
+ - /lib/modules:/lib/modules:ro
+ - /sys/fs/cgroup:/sys/fs/cgroup:rw
+ - /usr/src:/usr/src:ro
+ groups:
+ - controllers
+ - cephs
+ - computes
+provisioner:
+ name: ansible
+ config_options:
+ connection:
+ pipelining: true
+ tags:
+ skip: >-
+ sysctl,
+ ethtool
+ inventory:
+ group_vars:
+ all:
+ # Ceph
+ ceph_fsid: ${MOLECULE_CEPH_FSID:-"d1f9e453-f13a-4d30-9ab1-e5ae1d87b67f"}
+ ceph_conf_overrides:
+ - section: global
+ option: osd crush chooseleaf type
+ value: 0
+ - section: mon
+ option: auth allow insecure global id reclaim
+ value: false
+ # Kubernetes
+ kubernetes_keepalived_interface: eth0
+ kubernetes_keepalived_vrid: 42
+ kubernetes_keepalived_vip: 10.96.240.10
+ kubernetes_hostname: 10.96.240.10
+ # CNI
+ cilium_helm_values:
+ operator:
+ replicas: 1
+ # CSI
+ csi_driver: ${MOLECULE_CSI_DRIVER:-"local-path-provisioner"}
+ ceph_csi_rbd_helm_values:
+ provisioner:
+ replicaCount: 1
+ # Certificates
+ cluster_issuer_type: self-signed
+ # Ingress
+ ingress_nginx_helm_values:
+ controller:
+ config:
+ worker-processes: 2
+ # Percona XtraDB Cluster
+ percona_xtradb_cluster_spec:
+ allowUnsafeConfigurations: true
+ pxc:
+ size: 1
+ haproxy:
+ size: 1
+ # Common
+ domain_name: "{{ (lookup('env', 'HOST_IP') | default(ansible_default_ipv4.address, true)).replace('.', '-') }}.nip.io"
+ openstack_helm_endpoints_region_name: RegionOne
+ # Keycloak
+ keycloak_host: "keycloak.{{ domain_name }}"
+ keycloak_database_password: secrete123
+ keycloak_admin_password: secrete123
+ # Monitoring
+ grafana_keycloak_client_secret: secrete123
+ kube_prometheus_stack_grafana_host: "grafana.{{ domain_name }}"
+ kube_prometheus_stack_grafana_admin_password: secrete123
+ # Memcached
+ openstack_helm_endpoints_memcached_secret_key: secrete123
+ # RabbitMQ
+ rabbitmq_spec:
+ resources:
+ requests:
+ cpu: 250m
+ memory: 256Mi
+ # Keystone
+ openstack_helm_endpoints_keystone_api_host: "identity.{{ domain_name }}"
+ openstack_helm_endpoints_keystone_admin_password: secrete123
+ openstack_helm_endpoints_keystone_mariadb_password: secrete123
+ openstack_helm_endpoints_keystone_rabbitmq_password: secrete123
+ keystone_keycloak_client_secret: secrete123
+ keystone_oidc_crypto_passphrase: secrete123
+ keystone_helm_values:
+ pod:
+ replicas:
+ api: 1
+ # Horizon
+ openstack_helm_endpoints_horizon_api_host: "dashboard.{{ domain_name }}"
+ openstack_helm_endpoints_horizon_mariadb_password: secrete123
+ horizon_helm_values:
+ pod:
+ replicas:
+ server: 1
+ cephs:
+ ceph_osd_devices:
+ - "/dev/ceph-{{ inventory_hostname_short }}-osd0/data"
+ - "/dev/ceph-{{ inventory_hostname_short }}-osd1/data"
+ - "/dev/ceph-{{ inventory_hostname_short }}-osd2/data"
+ # options:
+ # inventory: "${MOLECULE_EPHEMERAL_DIRECTORY}/workspace"
+ # inventory:
+ # links:
+ # host_vars: "${MOLECULE_SCENARIO_DIRECTORY}/host_vars"
+ # group_vars: "${MOLECULE_SCENARIO_DIRECTORY}/group_vars"
+verifier:
+ name: ansible
diff --git a/molecule/shared/prepare/base.yml b/molecule/shared/prepare/base.yml
new file mode 100644
index 0000000..917cb63
--- /dev/null
+++ b/molecule/shared/prepare/base.yml
@@ -0,0 +1,46 @@
+# Copyright (c) 2023 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: all
+ become: true
+ pre_tasks:
+ - name: Wait for systemd to complete initialization
+ ansible.builtin.command: systemctl is-system-running
+ register: systemctl_status
+ until: >
+ 'running' in systemctl_status.stdout or
+ 'degraded' in systemctl_status.stdout
+ retries: 30
+ delay: 5
+ changed_when: false
+ failed_when: systemctl_status.rc > 1
+
+ # TODO(mnaser): We should really just build our own image, since the base
+ # images we use are missing a whole bunch of dependencies
+ # and need to download a lot of things online.
+ - name: Fix Python installation
+ block:
+ - name: Get all Python packages
+ ansible.builtin.command: pip freeze
+ register: pip_freeze
+
+ - name: Uninstall all Python packages
+ ansible.builtin.pip:
+ name: "{{ pip_freeze.stdout_lines }}"
+ state: absent
+ tasks:
+ - name: Refresh cache & install "iptables"
+ ansible.builtin.package:
+ name: iptables
+ update_cache: true
diff --git a/molecule/shared/prepare/ceph.yml b/molecule/shared/prepare/ceph.yml
new file mode 100644
index 0000000..cd622d3
--- /dev/null
+++ b/molecule/shared/prepare/ceph.yml
@@ -0,0 +1,21 @@
+# Copyright (c) 2023 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.
+
+- ansible.builtin.import_playbook: vexxhost.ceph.create_fake_devices
+- ansible.builtin.import_playbook: vexxhost.ceph.site
+ vars:
+ ceph_osd_devices:
+ - "/dev/ceph-{{ inventory_hostname_short }}-osd0/data"
+ - "/dev/ceph-{{ inventory_hostname_short }}-osd1/data"
+ - "/dev/ceph-{{ inventory_hostname_short }}-osd2/data"
diff --git a/molecule/shared/prepare/kubernetes.yml b/molecule/shared/prepare/kubernetes.yml
new file mode 100644
index 0000000..cf27c63
--- /dev/null
+++ b/molecule/shared/prepare/kubernetes.yml
@@ -0,0 +1,68 @@
+# Copyright (c) 2023 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.
+
+- ansible.builtin.import_playbook: vexxhost.atmosphere.kubernetes
+
+# NOTE(mnaser): When using Docker with custom networks, it will use 127.0.0.11
+# as the DNS server which trips up the CoreDNS "loop" plugin.
+- name: Switch CoreDNS to use CloudFlare DNS
+ hosts: controllers[0]
+ become: true
+ tasks:
+ - name: Update CoreDNS ConfigMap
+ kubernetes.core.k8s:
+ state: present
+ definition:
+ apiVersion: v1
+ kind: ConfigMap
+ metadata:
+ name: coredns
+ namespace: kube-system
+ data:
+ Corefile: |
+ .:53 {
+ errors
+ health {
+ lameduck 5s
+ }
+ ready
+ kubernetes cluster.local in-addr.arpa ip6.arpa {
+ pods insecure
+ fallthrough in-addr.arpa ip6.arpa
+ ttl 30
+ }
+ prometheus :9153
+ forward . 1.1.1.1 {
+ max_concurrent 1000
+ }
+ cache 30
+ loop
+ reload
+ loadbalance
+ }
+ notify:
+ - Rollout CoreDNS
+ - Wait for CoreDNS to be ready
+ handlers:
+ - name: Rollout CoreDNS
+ command: kubectl -n kube-system rollout restart deploy/coredns
+ - name: Wait for CoreDNS to be ready
+ command: kubectl -n kube-system rollout status deploy/coredns
+
+- ansible.builtin.import_playbook: vexxhost.atmosphere.csi
+
+- hosts: controllers
+ become: true
+ roles:
+ - vexxhost.atmosphere.ingress_nginx
diff --git a/molecule/shared/prepare/neutron.yml b/molecule/shared/prepare/neutron.yml
new file mode 100644
index 0000000..6d647f3
--- /dev/null
+++ b/molecule/shared/prepare/neutron.yml
@@ -0,0 +1,25 @@
+# Copyright (c) 2023 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
+ become: true
+ tasks:
+ - name: Set masquerade rule
+ become: yes
+ ansible.builtin.iptables:
+ table: nat
+ chain: POSTROUTING
+ source: 10.96.250.0/24
+ out_interface: "{{ ansible_default_ipv4.interface }}"
+ jump: MASQUERADE