From 8996b83adad98dfff94064405f3674798f7ccc54 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@redhat.com> Date: Wed, 15 Nov 2023 14:28:43 -0700 Subject: [PATCH] feat: support for ostree systems Feature: Allow running and testing the role with ostree managed nodes. Reason: We have users who want to use the role to manage ostree systems. Result: Users can use the role to manage ostree managed nodes. Signed-off-by: Rich Megginson <rmeggins@redhat.com> --- .ansible-lint | 1 + .ostree/README.md | 3 + .ostree/get_ostree_data.sh | 123 +++++++++++++++++++++++++++++++ .ostree/packages-runtime.txt | 4 + .ostree/packages-testing.txt | 1 + .sanity-ansible-ignore-2.12.txt | 1 + .sanity-ansible-ignore-2.13.txt | 1 + .sanity-ansible-ignore-2.14.txt | 1 + .sanity-ansible-ignore-2.15.txt | 1 + .sanity-ansible-ignore-2.9.txt | 1 + README-ostree.md | 66 +++++++++++++++++ meta/collection-requirements.yml | 2 + tasks/set_vars.yml | 18 +++++ tests/tasks/setup.yml | 24 ++++++ tests/tests_cockpit.yml | 5 ++ tests/tests_default.yml | 4 +- tests/tests_default_vars.yml | 3 + tests/tests_example.yml | 3 + tests/tests_sssd.yml | 3 + 19 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 .ostree/README.md create mode 100755 .ostree/get_ostree_data.sh create mode 100644 .ostree/packages-runtime.txt create mode 100644 .ostree/packages-testing.txt create mode 100644 .sanity-ansible-ignore-2.12.txt create mode 100644 .sanity-ansible-ignore-2.13.txt create mode 100644 .sanity-ansible-ignore-2.14.txt create mode 100644 .sanity-ansible-ignore-2.15.txt create mode 100644 .sanity-ansible-ignore-2.9.txt create mode 100644 README-ostree.md create mode 100644 tests/tasks/setup.yml diff --git a/.ansible-lint b/.ansible-lint index 1474aad..34c98ee 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -22,5 +22,6 @@ exclude_paths: - examples/roles/ mock_modules: - ini_file + - ansible.utils.update_fact mock_roles: - linux-system-roles.tlog diff --git a/.ostree/README.md b/.ostree/README.md new file mode 100644 index 0000000..f5e6931 --- /dev/null +++ b/.ostree/README.md @@ -0,0 +1,3 @@ +*NOTE*: The `*.txt` files are used by `get_ostree_data.sh` to create the lists +of packages, and to find other system roles used by this role. DO NOT use them +directly. diff --git a/.ostree/get_ostree_data.sh b/.ostree/get_ostree_data.sh new file mode 100755 index 0000000..7c32524 --- /dev/null +++ b/.ostree/get_ostree_data.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +set -euo pipefail + +role_collection_dir="${ROLE_COLLECTION_DIR:-fedora/linux_system_roles}" +ostree_dir="${OSTREE_DIR:-"$(dirname "$(realpath "$0")")"}" + +if [ -z "${4:-}" ] || [ "${1:-}" = help ] || [ "${1:-}" = -h ]; then + cat <<EOF +Usage: $0 packages [runtime|testing] DISTRO-MAJOR[.MINOR] [json|yaml|raw|toml] +The script will use the packages and roles files in $ostree_dir to +construct the list of packages needed to build the ostree image. The script +will output the list of packages in the given format +- json is a JSON list like ["pkg1","pkg2",....,"pkgN"] +- yaml is the YAML list format +- raw is the list of packages, one per line +- toml is a list of [[packages]] elements as in https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/composing_installing_and_managing_rhel_for_edge_images/index#creating-an-image-builder-blueprint-for-a-rhel-for-edge-image-using-the-command-line-interface_composing-a-rhel-for-edge-image-using-image-builder-command-line +The DISTRO-MAJOR.MINOR is the same format used by Ansible for distribution e.g. CentOS-8, RedHat-8.9, etc. +EOF + exit 1 +fi +category="$1" +pkgtype="$2" +distro_ver="$3" +format="$4" +pkgtypes=("$pkgtype") +if [ "$pkgtype" = testing ]; then + pkgtypes+=(runtime) +fi + +get_rolepath() { + local ostree_dir role rolesdir roles_parent_dir + ostree_dir="$1" + role="$2" + roles_parent_dir="$(dirname "$(dirname "$ostree_dir")")" + rolesdir="$roles_parent_dir/$role/.ostree" + # assumes collection format + if [ -d "$rolesdir" ]; then + echo "$rolesdir" + return 0 + fi + # assumes legacy role format like linux-system-roles.$role/ + for rolesdir in "$roles_parent_dir"/*-system-roles."$role"/.ostree; do + if [ -d "$rolesdir" ]; then + echo "$rolesdir" + return 0 + fi + done + # look elsewhere + if [ -n "${ANSIBLE_COLLECTIONS_PATHS:-}" ]; then + for pth in ${ANSIBLE_COLLECTIONS_PATHS//:/ }; do + rolesdir="$pth/ansible_collections/$role_collection_dir/roles/$role/.ostree" + if [ -d "$rolesdir" ]; then + echo "$rolesdir" + return 0 + fi + done + fi + return 1 +} + +get_packages() { + local ostree_dir pkgtype pkgfile rolefile + ostree_dir="$1" + for pkgtype in "${pkgtypes[@]}"; do + for suff in "" "-$distro" "-${distro}-${major_ver}" "-${distro}-${ver}"; do + pkgfile="$ostree_dir/packages-${pkgtype}${suff}.txt" + if [ -f "$pkgfile" ]; then + cat "$pkgfile" + fi + done + rolefile="$ostree_dir/roles-${pkgtype}.txt" + if [ -f "$rolefile" ]; then + local roles role rolepath + roles="$(cat "$rolefile")" + for role in $roles; do + rolepath="$(get_rolepath "$ostree_dir" "$role")" + get_packages "$rolepath" + done + fi + done | sort -u +} + +format_packages_json() { + local comma pkgs pkg + comma="" + pkgs="[" + while read -r pkg; do + pkgs="${pkgs}${comma}\"${pkg}\"" + comma=, + done + pkgs="${pkgs}]" + echo "$pkgs" +} + +format_packages_raw() { + cat +} + +format_packages_yaml() { + while read -r pkg; do + echo "- $pkg" + done +} + +format_packages_toml() { + while read -r pkg; do + echo "[[packages]]" + echo "name = \"$pkg\"" + echo "version = \"*\"" + done +} + +distro="${distro_ver%%-*}" +ver="${distro_ver##*-}" +if [[ "$ver" =~ ^([0-9]*) ]]; then + major_ver="${BASH_REMATCH[1]}" +else + echo ERROR: cannot parse major version number from version "$ver" + exit 1 +fi + +"get_$category" "$ostree_dir" | "format_${category}_$format" diff --git a/.ostree/packages-runtime.txt b/.ostree/packages-runtime.txt new file mode 100644 index 0000000..933fd5d --- /dev/null +++ b/.ostree/packages-runtime.txt @@ -0,0 +1,4 @@ +authselect +cockpit-session-recording +sssd +tlog diff --git a/.ostree/packages-testing.txt b/.ostree/packages-testing.txt new file mode 100644 index 0000000..c3153ef --- /dev/null +++ b/.ostree/packages-testing.txt @@ -0,0 +1 @@ +cockpit diff --git a/.sanity-ansible-ignore-2.12.txt b/.sanity-ansible-ignore-2.12.txt new file mode 100644 index 0000000..5309188 --- /dev/null +++ b/.sanity-ansible-ignore-2.12.txt @@ -0,0 +1 @@ +roles/tlog/.ostree/get_ostree_data.sh shebang!skip diff --git a/.sanity-ansible-ignore-2.13.txt b/.sanity-ansible-ignore-2.13.txt new file mode 100644 index 0000000..5309188 --- /dev/null +++ b/.sanity-ansible-ignore-2.13.txt @@ -0,0 +1 @@ +roles/tlog/.ostree/get_ostree_data.sh shebang!skip diff --git a/.sanity-ansible-ignore-2.14.txt b/.sanity-ansible-ignore-2.14.txt new file mode 100644 index 0000000..5309188 --- /dev/null +++ b/.sanity-ansible-ignore-2.14.txt @@ -0,0 +1 @@ +roles/tlog/.ostree/get_ostree_data.sh shebang!skip diff --git a/.sanity-ansible-ignore-2.15.txt b/.sanity-ansible-ignore-2.15.txt new file mode 100644 index 0000000..5309188 --- /dev/null +++ b/.sanity-ansible-ignore-2.15.txt @@ -0,0 +1 @@ +roles/tlog/.ostree/get_ostree_data.sh shebang!skip diff --git a/.sanity-ansible-ignore-2.9.txt b/.sanity-ansible-ignore-2.9.txt new file mode 100644 index 0000000..5309188 --- /dev/null +++ b/.sanity-ansible-ignore-2.9.txt @@ -0,0 +1 @@ +roles/tlog/.ostree/get_ostree_data.sh shebang!skip diff --git a/README-ostree.md b/README-ostree.md new file mode 100644 index 0000000..a9f0185 --- /dev/null +++ b/README-ostree.md @@ -0,0 +1,66 @@ +# rpm-ostree + +The role supports running on [rpm-ostree](https://coreos.github.io/rpm-ostree/) +systems. The primary issue is that the `/usr` filesystem is read-only, and the +role cannot install packages. Instead, it will just verify that the necessary +packages and any other `/usr` files are pre-installed. The role will change the +package manager to one that is compatible with `rpm-ostree` systems. + +## Building + +To build an ostree image for a particular operating system distribution and +version, use the script `.ostree/get_ostree_data.sh` to get the list of +packages. If the role uses other system roles, then the script will include the +packages for the other roles in the list it outputs. The list of packages will +be sorted in alphanumeric order. + +Usage: + +```bash +.ostree/get_ostree_data.sh packages runtime DISTRO-VERSION FORMAT +``` + +`DISTRO-VERSION` is in the format that Ansible uses for `ansible_distribution` +and `ansible_distribution_version` - for example, `Fedora-38`, `CentOS-8`, +`RedHat-9.4` + +`FORMAT` is one of `toml`, `json`, `yaml`, `raw` + +* `toml` - each package in a TOML `[[packages]]` element + +```toml +[[packages]] +name = "package-a" +version = "*" +[[packages]] +name = "package-b" +version = "*" +... +``` + +* `yaml` - a YAML list of packages + +```yaml +- package-a +- package-b +... +``` + +* `json` - a JSON list of packages + +```json +["package-a","package-b",...] +``` + +* `raw` - a plain text list of packages, one per line + +```bash +package-a +package-b +... +``` + +What format you choose depends on which image builder you are using. For +example, if you are using something based on +[osbuild-composer](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/composing_installing_and_managing_rhel_for_edge_images/index#creating-an-image-builder-blueprint-for-a-rhel-for-edge-image-using-the-command-line-interface_composing-a-rhel-for-edge-image-using-image-builder-command-line), +you will probably want to use the `toml` output format. diff --git a/meta/collection-requirements.yml b/meta/collection-requirements.yml index afc836d..3e9698f 100644 --- a/meta/collection-requirements.yml +++ b/meta/collection-requirements.yml @@ -1,3 +1,5 @@ --- collections: + - name: ansible.posix + - name: ansible.utils - name: community.general diff --git a/tasks/set_vars.yml b/tasks/set_vars.yml index 60b6356..406f6c9 100644 --- a/tasks/set_vars.yml +++ b/tasks/set_vars.yml @@ -5,6 +5,24 @@ when: __tlog_required_facts | difference(ansible_facts.keys() | list) | length > 0 +- name: Ensure correct package manager for ostree systems + vars: + ostree_pkg_mgr: ansible.posix.rhel_rpm_ostree + ostree_booted_file: /run/ostree-booted + when: ansible_facts.pkg_mgr | d("") != ostree_pkg_mgr + block: + - name: Check if system is ostree + stat: + path: "{{ ostree_booted_file }}" + register: __ostree_booted_stat + + - name: Set package manager to use for ostree + ansible.utils.update_fact: + updates: + - path: ansible_facts.pkg_mgr + value: "{{ ostree_pkg_mgr }}" + when: __ostree_booted_stat.stat.exists + - name: Set platform/version specific variables include_vars: "{{ __vars_file }}" loop: diff --git a/tests/tasks/setup.yml b/tests/tasks/setup.yml new file mode 100644 index 0000000..cb7cd00 --- /dev/null +++ b/tests/tasks/setup.yml @@ -0,0 +1,24 @@ +--- +# common test setup tasks +- name: Check if system is ostree + stat: + path: "{{ ostree_booted_file }}" + register: __ostree_booted_stat + vars: + ostree_booted_file: /run/ostree-booted + +- name: Skip test if not supported on ostree + meta: end_host + when: + - __ostree_booted_stat.stat.exists + - __tlog_unsupported_ostree | d(false) + +- name: Ensure sssd user/group exist in /etc files + shell: | + if ! grep -q ^sssd /etc/passwd && grep -q ^sssd /usr/lib/passwd; then + grep ^sssd /usr/lib/passwd >> /etc/passwd + fi + if ! grep -q ^sssd /etc/group && grep -q ^sssd /usr/lib/group; then + grep ^sssd /usr/lib/group >> /etc/group + fi + when: __ostree_booted_stat.stat.exists diff --git a/tests/tests_cockpit.yml b/tests/tests_cockpit.yml index 0a229b7..1a6d0cf 100644 --- a/tests/tests_cockpit.yml +++ b/tests/tests_cockpit.yml @@ -2,6 +2,11 @@ - name: Test support for autoinstall of cockpit-session-recording hosts: all tasks: + - name: Test setup and check for ostree + include_tasks: tasks/setup.yml + vars: + __tlog_unsupported_ostree: true + - name: Get the rpm package facts package_facts: diff --git a/tests/tests_default.yml b/tests/tests_default.yml index 4665b5e..37fd6f3 100644 --- a/tests/tests_default.yml +++ b/tests/tests_default.yml @@ -1,7 +1,9 @@ --- - name: Ensure that the role runs with default parameters hosts: all - roles: - linux-system-roles.tlog gather_facts: false + pre_tasks: + - name: Test setup and check for ostree + include_tasks: tasks/setup.yml diff --git a/tests/tests_default_vars.yml b/tests/tests_default_vars.yml index 93f5075..4c73c30 100644 --- a/tests/tests_default_vars.yml +++ b/tests/tests_default_vars.yml @@ -3,6 +3,9 @@ hosts: all roles: - linux-system-roles.tlog + pre_tasks: + - name: Test setup and check for ostree + include_tasks: tasks/setup.yml tasks: - name: Check that all variables are defined assert: diff --git a/tests/tests_example.yml b/tests/tests_example.yml index 391fc06..f60b308 100644 --- a/tests/tests_example.yml +++ b/tests/tests_example.yml @@ -7,3 +7,6 @@ tlog_scope_sssd: some tlog_users_sssd: - recordeduser + pre_tasks: + - name: Test setup and check for ostree + include_tasks: tasks/setup.yml diff --git a/tests/tests_sssd.yml b/tests/tests_sssd.yml index 5c2b20a..6b0c785 100644 --- a/tests/tests_sssd.yml +++ b/tests/tests_sssd.yml @@ -3,6 +3,9 @@ hosts: all tasks: + - name: Test setup and check for ostree + include_tasks: tasks/setup.yml + - name: Run role with default sssd settings import_role: name: linux-system-roles.tlog