[stable/zed] feat: containerize openstack cli (#1173)

This is an automated cherry-pick of #972
/assign mnaser
diff --git a/roles/barbican/tasks/main.yml b/roles/barbican/tasks/main.yml
index 2652cf3..3894ab5 100644
--- a/roles/barbican/tasks/main.yml
+++ b/roles/barbican/tasks/main.yml
@@ -64,9 +64,13 @@
 - name: Add implied roles
   run_once: true
   ansible.builtin.shell: |
+    set -o posix
+    source /etc/profile.d/atmosphere.sh
     openstack implied role create \
       --implied-role {{ item.implies }} \
       {{ item.role }}
+  args:
+    executable: /bin/bash
   loop:
     - role: member
       implies: creator
diff --git a/roles/defaults/vars/main.yml b/roles/defaults/vars/main.yml
index 3661f61..cfd0590 100644
--- a/roles/defaults/vars/main.yml
+++ b/roles/defaults/vars/main.yml
@@ -156,6 +156,7 @@
   octavia_health_manager: "registry.atmosphere.dev/library/octavia:{{ atmosphere_release }}"
   octavia_housekeeping: "registry.atmosphere.dev/library/octavia:{{ atmosphere_release }}"
   octavia_worker: "registry.atmosphere.dev/library/octavia:{{ atmosphere_release }}"
+  openstack_cli: "registry.atmosphere.dev/library/python-openstackclient:{{ atmosphere_release }}"
   openvswitch_db_server: "registry.atmosphere.dev/library/openvswitch:{{ atmosphere_release }}"
   openvswitch_vswitchd: "registry.atmosphere.dev/library/openvswitch:{{ atmosphere_release }}"
   ovn_controller: "registry.atmosphere.dev/library/ovn-host:{{ atmosphere_release }}"
diff --git a/roles/octavia/tasks/generate_resources.yml b/roles/octavia/tasks/generate_resources.yml
index 32ee815..af7417d 100644
--- a/roles/octavia/tasks/generate_resources.yml
+++ b/roles/octavia/tasks/generate_resources.yml
@@ -85,9 +85,13 @@
 - name: Set binding for ports
   changed_when: false
   ansible.builtin.shell: |
+    set -o posix
+    source /etc/profile.d/atmosphere.sh
     openstack port set \
       --host {{ hostvars[item]['ansible_fqdn'] }} \
       octavia-health-manager-port-{{ hostvars[item]['inventory_hostname_short'] }}
+  args:
+    executable: /bin/bash
   environment:
     OS_CLOUD: atmosphere
   loop: "{{ groups['controllers'] }}"
diff --git a/roles/octavia/tasks/main.yml b/roles/octavia/tasks/main.yml
index c5d6491..a984c6b 100644
--- a/roles/octavia/tasks/main.yml
+++ b/roles/octavia/tasks/main.yml
@@ -133,9 +133,13 @@
 - name: Add implied roles
   run_once: true
   ansible.builtin.shell: |
+    set -o posix
+    source /etc/profile.d/atmosphere.sh
     openstack implied role create \
       --implied-role {{ item.implies }} \
       {{ item.role }}
+  args:
+    executable: /bin/bash
   loop:
     - role: member
       implies: load-balancer_member
diff --git a/roles/openstack_cli/defaults/main.yml b/roles/openstack_cli/defaults/main.yml
index 06e41b5..9a58d41 100644
--- a/roles/openstack_cli/defaults/main.yml
+++ b/roles/openstack_cli/defaults/main.yml
@@ -1,19 +1,18 @@
----
-# .. vim: foldmarker=[[[,]]]:foldmethod=marker
-
-# .. Copyright (C) 2022 VEXXHOST, Inc.
-# .. SPDX-License-Identifier: Apache-2.0
-
-# Default variables
-# =================
-
-# .. contents:: Sections
-#    :local:
-
-
-# .. envvar:: openstack_cli_packages [[[
+# Copyright (c) 2024 VEXXHOST, Inc.
 #
-# List of packages to install for OpenStack CLI
+# 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(fitbeard): This is to accomodate for the uninstallation of the old packages
 openstack_cli_packages:
   - python3-barbicanclient
   - python3-designateclient
@@ -29,7 +28,5 @@
   - python3-senlinclient
   - python3-swiftclient
 
-                                                                   # ]]]
-
 # URL for the Ubuntu Cloud Archive repository
 openstack_cli_cloud_archive_repo: deb http://ubuntu-cloud.archive.canonical.com/ubuntu {{ ansible_distribution_release }}-updates/yoga main
diff --git a/roles/openstack_cli/meta/main.yml b/roles/openstack_cli/meta/main.yml
index 9b0260e..1bda249 100644
--- a/roles/openstack_cli/meta/main.yml
+++ b/roles/openstack_cli/meta/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2022 VEXXHOST, Inc.
+# Copyright (c) 2024 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
@@ -19,9 +19,17 @@
   min_ansible_version: 5.5.0
   standalone: false
   platforms:
+    - name: EL
+      versions:
+        - "8"
+        - "9"
     - name: Ubuntu
       versions:
         - focal
+        - jammy
 
 dependencies:
   - role: defaults
+  - role: vexxhost.containers.nerdctl
+    vars:
+      nerdctl_namespace: k8s.io
diff --git a/roles/openstack_cli/tasks/main.yml b/roles/openstack_cli/tasks/main.yml
index d0e8e2b..37ef184 100644
--- a/roles/openstack_cli/tasks/main.yml
+++ b/roles/openstack_cli/tasks/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2022 VEXXHOST, Inc.
+# Copyright (c) 2024 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
@@ -12,22 +12,24 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-- name: Install Ubuntu Cloud Archive keyring
+- name: Uninstall OpenStack client system packages
+  ansible.builtin.package:
+    name: "{{ openstack_cli_packages }}"
+    state: absent
+  when: ansible_facts['os_family'] in ['Debian']
+
+- name: Uninstall Ubuntu Cloud Archive keyring
   ansible.builtin.apt:
     name: ubuntu-cloud-keyring
-    state: present
+    state: absent
+  when: ansible_facts['os_family'] in ['Debian']
 
-- name: Add latest Ubuntu Cloud Archive repository
+- name: Remove Ubuntu Cloud Archive repository
   ansible.builtin.apt_repository:
     filename: ubuntu-cloud-archive
     repo: "{{ openstack_cli_cloud_archive_repo }}"
-    state: present
-  when: ansible_distribution_release == "focal"
-
-- name: Install OpenStack client
-  become: true
-  ansible.builtin.apt:
-    name: "{{ openstack_cli_packages }}"
+    state: absent
+  when: ansible_facts['os_family'] in ['Debian']
 
 - name: Generate OpenStack-Helm endpoints
   ansible.builtin.include_role:
@@ -43,3 +45,12 @@
     owner: root
     group: root
     mode: "0600"
+
+- name: Generate openstack aliases
+  become: true
+  ansible.builtin.template:
+    src: atmosphere.sh.j2
+    dest: /etc/profile.d/atmosphere.sh
+    owner: root
+    group: root
+    mode: "0644"
diff --git a/roles/openstack_cli/templates/atmosphere.sh.j2 b/roles/openstack_cli/templates/atmosphere.sh.j2
new file mode 100644
index 0000000..416a825
--- /dev/null
+++ b/roles/openstack_cli/templates/atmosphere.sh.j2
@@ -0,0 +1,14 @@
+alias osc='nerdctl run --rm --network host \
+      --volume $PWD:/opt --volume /tmp:/tmp \
+      --volume /etc/openstack:/etc/openstack:ro \
+{% if cluster_issuer_type is defined and cluster_issuer_type in ('self-signed', 'ca') %}
+      --volume {{ '/usr/local/share/ca-certificates/atmosphere.crt:/usr/local/share/ca-certificates/atmosphere.crt:ro' if ansible_facts['os_family']
+      in ['Debian'] else '/etc/pki/ca-trust/source/anchors/atmosphere.crt:/etc/pki/ca-trust/source/anchors/atmosphere.crt:ro' }} \
+{% endif %}
+      --env-file <(env | grep OS_) \
+      {{ atmosphere_images['openstack_cli'] }}'
+alias openstack='osc openstack'
+alias nova='osc nova'
+alias neutron='osc neutron'
+alias cinder='osc cinder'
+alias glance='osc glance'
diff --git a/roles/openstack_cli/templates/openrc.j2 b/roles/openstack_cli/templates/openrc.j2
index 188fb81..87e5e34 100644
--- a/roles/openstack_cli/templates/openrc.j2
+++ b/roles/openstack_cli/templates/openrc.j2
@@ -12,5 +12,5 @@
 export OS_PROJECT_NAME=admin
 
 {% if cluster_issuer_type is defined and cluster_issuer_type in ('self-signed', 'ca') %}
-export OS_CACERT=/usr/local/share/ca-certificates/atmosphere.crt
+export OS_CACERT={{ '/usr/local/share/ca-certificates' if ansible_facts['os_family'] in ['Debian'] else '/etc/pki/ca-trust/source/anchors' }}/atmosphere.crt
 {% endif %}
diff --git a/roles/openstacksdk/defaults/main.yml b/roles/openstacksdk/defaults/main.yml
new file mode 100644
index 0000000..27dc31a
--- /dev/null
+++ b/roles/openstacksdk/defaults/main.yml
@@ -0,0 +1,15 @@
+# Copyright (c) 2024 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.
+
+openstacksdk_version: "0.61.0"
diff --git a/roles/openstacksdk/tasks/main.yml b/roles/openstacksdk/tasks/main.yml
index 724f291..1a4c3b4 100644
--- a/roles/openstacksdk/tasks/main.yml
+++ b/roles/openstacksdk/tasks/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2022 VEXXHOST, Inc.
+# Copyright (c) 2024 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
@@ -14,7 +14,8 @@
 
 - name: Install openstacksdk
   ansible.builtin.pip:
-    name: openstacksdk==0.61.0
+    name: openstacksdk
+    version: "{{ openstacksdk_version }}"
 
 - name: Create openstack config directory
   become: true
@@ -32,4 +33,4 @@
     dest: /etc/openstack/clouds.yaml
     owner: root
     group: root
-    mode: '0600'
+    mode: "0600"
diff --git a/roles/openstacksdk/templates/clouds.yaml.j2 b/roles/openstacksdk/templates/clouds.yaml.j2
index b855a63..efb2245 100644
--- a/roles/openstacksdk/templates/clouds.yaml.j2
+++ b/roles/openstacksdk/templates/clouds.yaml.j2
@@ -9,5 +9,5 @@
       project_domain_name: Default
     region_name: "{{ openstack_helm_endpoints_keystone_region_name }}"
 {% if cluster_issuer_type is defined and cluster_issuer_type in ('self-signed', 'ca') %}
-    cacert: /usr/local/share/ca-certificates/atmosphere.crt
+    cacert: "{{ '/usr/local/share/ca-certificates' if ansible_facts['os_family'] in ['Debian'] else '/etc/pki/ca-trust/source/anchors' }}/atmosphere.crt"
 {% endif %}