diff --git a/.github/actions/container_task_prep/action.yaml b/.github/actions/container_task_prep/action.yaml index 7cef38d..50af0bb 100644 --- a/.github/actions/container_task_prep/action.yaml +++ b/.github/actions/container_task_prep/action.yaml @@ -24,9 +24,9 @@ runs: # ...possibly this should be moved into the # install_build_artifact task scripts. set_platform_globals - if [[ "${platform}" == 'Rocky' ]]; then - # The Rocky9 container, at least, is missing openvox-agent's - # systemd dependency... + if [[ "${platform}" == 'Rocky' ]] || [[ "${platform}" == 'Fedora' ]]; then + # The Rocky9 and Fedora containers, at least, are missing + # openvox-agent's systemd dependency... exec_and_capture dnf install -y systemd if [[ "${os_major_version}" == '8' ]]; then # ...and the Rocky8 container is missing findutils. diff --git a/.github/workflows/pr_testing_install_build_artifact.yaml b/.github/workflows/pr_testing_install_build_artifact.yaml index 2320095..6532a45 100644 --- a/.github/workflows/pr_testing_install_build_artifact.yaml +++ b/.github/workflows/pr_testing_install_build_artifact.yaml @@ -72,3 +72,74 @@ jobs: PT__installdir: ${{ github.workspace }} PT_version: "8.15.0" run: ./openvox_bootstrap/tasks/install_build_artifact_linux.sh + + test-install-build-artifact-task-noarch: + strategy: + matrix: + package: + - name: openvox-server + version: 8.8.0 + - name: openvoxdb + version: 8.9.0 + - name: openvoxdb-termini + version: 8.9.0 + details: + - image: almalinux:9 + prereqs: + - java-17-openjdk-headless + - net-tools + - procps-ng + - which + - image: debian:12 + prereqs: + - openjdk-17-jre-headless + - net-tools + - procps + - image: ubuntu:24.04 + prereqs: + - openjdk-17-jre-headless + - net-tools + - procps + runs-on: ubuntu-latest + container: ${{ matrix.details.image }} + steps: + - uses: actions/checkout@v4 + with: + path: openvox_bootstrap + - id: prep + uses: ./openvox_bootstrap/.github/actions/container_task_prep + - name: Run openvox-agent install task manually + env: + PT__installdir: ${{ github.workspace }} + PT_version: "8.19.1" + run: ./openvox_bootstrap/tasks/install_build_artifact_linux.sh + - name: Install prerequisites + shell: bash + env: + PREREQ_PACKAGES: ${{ join(matrix.details.prereqs, ',') }} + run: |- + set +e + /opt/puppetlabs/bin/puppet apply --detailed-exitcodes < installed + } + EOS + exitcode=$? + set -e + # Expect package changes and no failures. + [[ "${exitcode}" -eq 2 ]] + - name: Test noarch package installation + env: + PT__installdir: ${{ github.workspace }} + PT_package: ${{ matrix.package.name }} + PT_version: ${{ matrix.package.version }} + run: ./openvox_bootstrap/tasks/install_build_artifact_linux.sh + - name: Verify openvox-server is installed + shell: bash + env: + PACKAGE: ${{ matrix.package.name }} + VERSION: ${{ matrix.package.version }} + run: |- + /opt/puppetlabs/bin/puppet resource package "${PACKAGE}" > openvox-package.status + cat openvox-package.status + grep "ensure.*=>.*'${VERSION}" openvox-package.status diff --git a/.github/workflows/pr_testing_with_nested_vms.yml b/.github/workflows/pr_testing_with_nested_vms.yml index 829931b..a4b4026 100644 --- a/.github/workflows/pr_testing_with_nested_vms.yml +++ b/.github/workflows/pr_testing_with_nested_vms.yml @@ -58,9 +58,15 @@ jobs: "cpu_mode": "host-model" } ] + - name: Capture dereferenced inventory for use with openvox_bootstrap + working-directory: kvm_automation_tooling + run: |- + bolt inventory --inventory terraform/instances/inventory.test.yaml show --format json --detail | \ + jq '.inventory | with_entries(select(.key == "targets")) | del(.targets[0].groups)' | \ + yq -P > ../inventory.yaml - name: Run openvox_bootstrap::install task on nested vm run: |- - bolt task run openvox_bootstrap::install --inventory kvm_automation_tooling/terraform/instances/inventory.test.yaml --targets test-agent-1 + bolt task run openvox_bootstrap::install --inventory inventory.yaml --targets test-agent-1 - name: Verify openvox-agent is installed run: |- - bolt task run openvox_bootstrap::check version=8 test=gt --inventory kvm_automation_tooling/terraform/instances/inventory.test.yaml --targets test-agent-1 + bolt task run openvox_bootstrap::check version=8 test=gt --inventory inventory.yaml --targets test-agent-1 diff --git a/files/common.sh b/files/common.sh index a5c1009..358c1ae 100644 --- a/files/common.sh +++ b/files/common.sh @@ -377,3 +377,136 @@ refresh_package_cache() { exit 1 fi } + +# Test whether the given package name matches a list of +# openvox packages that are noarch. +noarch_package() { + local _package="$1" + + # List of noarch packages. + local noarch_packages=( + 'openvox-server' + 'openvoxdb' + 'openvoxdb-termini' + ) + + for pkg in "${noarch_packages[@]}"; do + if [[ "${_package}" == "${pkg}" ]]; then + return 0 + fi + done + + return 1 +} + +# Lookup the cpu architecture and set it as cpu_arch. +# Translates x86_64 to amd64 and aarch64 to arm64 for debian/ubuntu. +set_cpu_architecture() { + local _family="$1" + + local _arch + _arch=$(uname -m) + case "${_family}" in + debian|ubuntu) + case "${_arch}" in + x86_64) + cpu_arch="amd64" + ;; + aarch64) + cpu_arch="arm64" + ;; + *) + cpu_arch="${_arch}" + ;; + esac + ;; + *) + cpu_arch="${_arch}" + ;; + esac + export cpu_arch # quiets shellcheck SC2034 + assigned 'cpu_arch' +} + +# Lookup the architecture for the given package and set it as +# package_arch. +# +# This will either be noarch/all depending on the platform and +# whether the package name matches an openvox noarch_package(), +# or it will be the cpu_arch. +set_package_architecture() { + local _package="$1" + local _os_family="${2:-${os_family}}" + + if noarch_package "${_package}"; then + case "${_os_family}" in + debian|ubuntu) + package_arch='all' + ;; + *) + package_arch='noarch' + ;; + esac + else + set_cpu_architecture "${_os_family}" + package_arch="${cpu_arch}" + fi + export package_arch # quiets shellcheck SC2034 + assigned 'package_arch' +} + +# Based on platform, package and version set: +# package_name - the name of the build artifact package +# package_url - the url to download the build artifact package +# +# Currently this is based on the structure of the package repository +# at https://artifacts.voxpupuli.org, which is a page +# that provides a summary of links to artifacts contained in an S3 +# bucket hosted by Oregon State University Open Source Lab. +# +# Example rpm: +# https://artifacts.voxpupuli.org/openvox-agent/8.15.0/openvox-agent-8.15.0-1.el8.x86_64.rpm +# Example deb: +# https://artifacts.voxpupuli.org/openvox-agent/8.15.0/openvox-agent_8.15.0-1%2Bdebian12_amd64.deb +set_artifacts_package_url() { + local _artifacts_source="$1" + local _package="$2" + local _version="$3" + + set_package_type "${os_family}" + set_package_architecture "${_package}" "${os_family}" + + case "${package_type}" in + rpm) + # Account for a fedora naming quirk in the build artifacts. + if [[ "${os_family}" == "fedora" ]]; then + _os_family="fc" + else + _os_family="${os_family}" + fi + package_name="${_package}-${_version}-1.${_os_family}${os_major_version}.${package_arch}.${package_type}" + ;; + deb) + package_name="${_package}_${_version}-1%2B${os_family}${os_full_version}_${package_arch}.${package_type}" + ;; + *) + fail "Unhandled package type: '${package_type}'" + ;; + esac + + case "${_package}" in + openvoxdb-termini) + local _package_dir='openvoxdb' + ;; + *) + local _package_dir="${_package}" + ;; + esac + + package_url="${_artifacts_source}/${_package_dir}/${_version}/${package_name}" + + export package_name # quiets shellcheck SC2034 + assigned 'package_name' + export package_url # quiets shellcheck SC2034 + assigned 'package_url' +} diff --git a/spec/unit/bash/common_sh_spec.rb b/spec/unit/bash/common_sh_spec.rb index d5af21c..8e24e74 100644 --- a/spec/unit/bash/common_sh_spec.rb +++ b/spec/unit/bash/common_sh_spec.rb @@ -261,38 +261,26 @@ end it 'sets platform globals' do - output, status = test(<<~EOT) - set_platform_globals - echo "set platform=$platform" - echo "set os_full_version=$os_full_version" - echo "set os_major_version=$os_major_version" - echo "set os_family=$os_family" - EOT + output, status = test('set_platform_globals') expect(status.success?).to be(true) - expect(output).to include('set platform=Ubuntu') - expect(output).to include('set os_full_version=24.04') - expect(output).to include('set os_major_version=24') - expect(output).to include('set os_family=ubuntu') + expect(output).to include('Assigned platform=Ubuntu') + expect(output).to include('Assigned os_full_version=24.04') + expect(output).to include('Assigned os_major_version=24') + expect(output).to include('Assigned os_family=ubuntu') end context 'with a pre-release' do let(:os) { :debian13 } it 'uses codename when release is n/a' do - output, status = test(<<~EOT) - set_platform_globals - echo "set platform=$platform" - echo "set os_full_version=$os_full_version" - echo "set os_major_version=$os_major_version" - echo "set os_family=$os_family" - EOT + output, status = test('set_platform_globals') expect(status.success?).to be(true) - expect(output).to include('set platform=Debian') - expect(output).to include('set os_full_version=13') - expect(output).to include('set os_major_version=13') - expect(output).to include('set os_family=debian') + expect(output).to include('Assigned platform=Debian') + expect(output).to include('Assigned os_full_version=13') + expect(output).to include('Assigned os_major_version=13') + expect(output).to include('Assigned os_family=debian') end end end @@ -308,13 +296,7 @@ it 'fails for an unknown platform' do mock_facts_task_bash_sh(:unknown) - output, status = test(<<~EOT) - set_platform_globals - echo "set platform=$platform" - echo "set os_full_version=$os_full_version" - echo "set os_major_version=$os_major_version" - echo "set os_family=$os_family" - EOT + output, status = test('set_platform_globals') expect(status.success?).to be(false) expect(output).to include("Unhandled platform: 'Unknown'") @@ -439,4 +421,160 @@ end end end + + context 'noarch_package' do + it 'returns 0 for a noarch package' do + output, status = test('noarch_package openvox-server') + + expect(status.success?).to be(true) + expect(output.strip).to be_empty + end + + it 'returns 1 for a non-noarch package' do + output, status = test('noarch_package foo') + + expect(status.success?).to be(false) + expect(output.strip).to be_empty + end + end + + context 'set_cpu_architecture' do + context 'debian or ubuntu' do + it 'sets x86_64 for amd64' do + allow_script.to receive_command(:uname).and_exec('echo x86_64') + output, status = test('set_cpu_architecture debian') + + expect(status.success?).to be(true) + expect(output).to include('Assigned cpu_arch=amd64') + end + + it 'sets arm64 for aarch64' do + allow_script.to receive_command(:uname).and_exec('echo aarch64') + output, status = test('set_cpu_architecture ubuntu') + + expect(status.success?).to be(true) + expect(output).to include('Assigned cpu_arch=arm64') + end + + it 'sets amd64 for amd64' do + allow_script.to receive_command(:uname).and_exec('echo amd64') + output, status = test('set_cpu_architecture debian') + + expect(status.success?).to be(true) + expect(output).to include('Assigned cpu_arch=amd64') + end + end + + context 'other' do + it 'sets what uname gives it' do + allow_script.to receive_command(:uname).and_exec('echo x86_64') + output, status = test('set_cpu_architecture el') + + expect(status.success?).to be(true) + expect(output).to include('Assigned cpu_arch=x86_64') + end + end + end + + context 'set_package_architecture' do + it 'sets all for debian noarch' do + output, status = test('set_package_architecture openvox-server debian') + + expect(status.success?).to be(true) + expect(output).to include('Assigned package_arch=all') + end + + it 'sets noarch for el noarch' do + output, status = test('set_package_architecture openvoxdb el') + + expect(status.success?).to be(true) + expect(output).to include('Assigned package_arch=noarch') + end + + it 'sets system arch otherwise' do + allow_script.to receive_command(:uname).and_exec('echo x86_64') + output, status = test('set_package_architecture openvox-agent el') + + expect(status.success?).to be(true) + expect(output).to include('Assigned cpu_arch=x86_64') + expect(output).to include('Assigned package_arch=x86_64') + end + end + + context 'set_artifacts_package_url' do + context 'deb' do + it 'builds a debian url' do + allow_script.to set_env('os_family', 'debian') + allow_script.to receive_command(:uname).and_exec('echo x86_64') + output, status = test('set_artifacts_package_url https://foo openvox-agent 8.18.0') + + expect(status.success?).to be(true) + package_name = 'openvox-agent_8.18.0-1%2Bdebian_amd64.deb' + expect(output).to include("Assigned package_name=#{package_name}") + expect(output).to include("Assigned package_url=https://foo/openvox-agent/8.18.0/#{package_name}") + end + + it 'builds a noarch package url for ubuntu' do + allow_script.to set_env('os_family', 'ubuntu') + output, status = test('set_artifacts_package_url https://foo openvox-server 8.9.0') + + expect(status.success?).to be(true) + package_name = 'openvox-server_8.9.0-1%2Bubuntu_all.deb' + expect(output).to include("Assigned package_name=#{package_name}") + expect(output).to include("Assigned package_url=https://foo/openvox-server/8.9.0/#{package_name}") + end + end + + context 'rpm' do + it 'builds a redhat url' do + allow_script.to set_env('os_family', 'el') + allow_script.to receive_command(:uname).and_exec('echo x86_64') + output, status = test('set_artifacts_package_url https://foo openvox-agent 8.18.0') + + expect(status.success?).to be(true) + package_name = 'openvox-agent-8.18.0-1.el.x86_64.rpm' + expect(output).to include("Assigned package_name=#{package_name}") + expect(output).to include("Assigned package_url=https://foo/openvox-agent/8.18.0/#{package_name}") + end + + it 'builds a noarch package url for redhat' do + allow_script.to set_env('os_family', 'el') + output, status = test('set_artifacts_package_url https://foo openvoxdb-termini 8.9.1') + + expect(status.success?).to be(true) + package_name = 'openvoxdb-termini-8.9.1-1.el.noarch.rpm' + expect(output).to include("Assigned package_name=#{package_name}") + expect(output).to include("Assigned package_url=https://foo/openvoxdb/8.9.1/#{package_name}") + end + + it 'builds a fedora url' do + allow_script.to set_env('os_family', 'fedora') + allow_script.to receive_command(:uname).and_exec('echo x86_64') + output, status = test('set_artifacts_package_url https://foo openvox-agent 8.18.0') + + expect(status.success?).to be(true) + package_name = 'openvox-agent-8.18.0-1.fc.x86_64.rpm' + expect(output).to include("Assigned package_name=#{package_name}") + expect(output).to include("Assigned package_url=https://foo/openvox-agent/8.18.0/#{package_name}") + end + end + + context 'pathing' do + it 'looks for openvoxdb in the openvoxdb dir' do + allow_script.to set_env('os_family', 'el') + output, status = test('set_artifacts_package_url https://foo openvoxdb 8.9.1') + + expect(status.success?).to be(true) + expect(output).to match(%r{Assigned package_url=https://foo/openvoxdb/8\.9\.1/}) + end + + it 'lookds for openvoxdb-termini in the openvoxdb dir as well' do + allow_script.to set_env('os_family', 'el') + output, status = test('set_artifacts_package_url https://foo openvoxdb-termini 8.9.1') + + expect(status.success?).to be(true) + expect(output).to match(%r{Assigned package_url=https://foo/openvoxdb/8\.9\.1/}) + end + end + end end diff --git a/tasks/install_build_artifact_linux.sh b/tasks/install_build_artifact_linux.sh index c9e0f7e..d08e82a 100755 --- a/tasks/install_build_artifact_linux.sh +++ b/tasks/install_build_artifact_linux.sh @@ -11,83 +11,10 @@ artifacts_source=${PT_artifacts_source:-https://artifacts.voxpupuli.org} # shellcheck source=files/common.sh source "${PT__installdir}/openvox_bootstrap/files/common.sh" -# Lookup the cpu architecture and set it as cpu_arch. -# Translates x86_64 to amd64 and aarch64 to arm64 for debian/ubuntu. -set_architecture() { - local _family="$1" - - local _arch - _arch=$(uname -m) - case "${_family}" in - debian|ubuntu) - case "${_arch}" in - x86_64) - cpu_arch="amd64" - ;; - aarch64) - cpu_arch="arm64" - ;; - *) - cpu_arch="${_arch}" - ;; - esac - ;; - *) - cpu_arch="${_arch}" - ;; - esac - - assigned 'cpu_arch' -} - -# Based on platform, package and version set: -# package_name - the name of the build artifact package -# package_url - the url to download the build artifact package -# -# Currently this is based on the structure of the package repository -# at https://artifacts.voxpupuli.org, which is a page -# that provides a summary of links to artifacts contained in an S3 -# bucket hosted by Oregon State University Open Source Lab. -# -# Example rpm: -# https://artifacts.voxpupuli.org/openvox-agent/8.15.0/openvox-agent-8.15.0-1.el8.x86_64.rpm -# Example deb: -# https://artifacts.voxpupuli.org/openvox-agent/8.15.0/openvox-agent_8.15.0-1%2Bdebian12_amd64.deb -set_package_url() { - local _platform="$1" - local _package="$2" - local _version="$3" - - set_package_type "${os_family}" - set_architecture "${os_family}" - - case "${package_type}" in - rpm) - # Account for a fedora naming quirk in the build artifacts. - if [[ "${os_family}" == "fedora" ]]; then - _os_family="fc" - else - _os_family="${os_family}" - fi - package_name="${_package}-${_version}-1.${_os_family}${os_major_version}.${cpu_arch}.${package_type}" - ;; - deb) - package_name="${_package}_${_version}-1%2B${os_family}${os_full_version}_${cpu_arch}.${package_type}" - ;; - *) - fail "Unhandled package type: '${package_type}'" - ;; - esac - package_url="${artifacts_source}/${_package}/${_version}/${package_name}" - - assigned 'package_name' - assigned 'package_url' -} - # Get platform information set_platform_globals # Set url to build artifacts package based on platform -set_package_url "${platform}" "${package}" "${version}" +set_artifacts_package_url "${artifacts_source}" "${package}" "${version}" # Download the build artifacts package to the tempdir. local_package="${tempdir}/${package_name}" download "${package_url}" "${local_package}"