diff --git a/.github/workflows/ci-live.yml b/.github/workflows/ci-live.yml new file mode 100644 index 0000000000..044657aa1d --- /dev/null +++ b/.github/workflows/ci-live.yml @@ -0,0 +1,59 @@ +name: CI - ISO definition + +on: + push: + paths: + # NOTE: GitHub Actions do not allow using YAML references, the same path + # list is used below for the pull request event. Keep both lists in sync!! + + # this file as well + - .github/workflows/ci-live.yml + # any change in the service subfolder + - live/** + + pull_request: + paths: + # NOTE: GitHub Actions do not allow using YAML references, the same path + # list is used above for the push event. Keep both lists in sync!! + + # this file as well + - .github/workflows/ci-live.yml + # any change in the service subfolder + - live/** + + # allow running manually + workflow_dispatch: + +jobs: + ruby_tests: + runs-on: ubuntu-latest + env: + COVERAGE: 1 + + defaults: + run: + working-directory: ./live + + strategy: + fail-fast: false + matrix: + distro: [ "tumbleweed" ] + + container: + image: registry.opensuse.org/yast/head/containers_${{matrix.distro}}/yast-ruby + + steps: + + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Configure and refresh repositories + # disable unused repositories to have faster refresh + run: zypper modifyrepo -d repo-non-oss repo-openh264 repo-update && zypper ref + + - name: Install Ruby development files + run: zypper --non-interactive install + make + + - name: Run the tests + run: make check diff --git a/autoinstallation/bin/agama-auto b/autoinstallation/bin/agama-auto index 5e1b4e76f5..b7b229f98e 100755 --- a/autoinstallation/bin/agama-auto +++ b/autoinstallation/bin/agama-auto @@ -6,7 +6,7 @@ export YAST_SKIP_XML_VALIDATION=1 if [ -z "$1" ] then - url=$(awk -F 'agama.auto=' '{sub(/ .*$/, "", $2); print $2}' < /proc/cmdline) + url=$( grep 'agama.auto=' < /run/agama/cmdline.d/agama.conf | awk -F 'agama.auto=' '{sub(/ .*$/, "", $2); print $2}' ) else url="$1" fi diff --git a/live/Makefile b/live/Makefile index fee753aa4c..bd99b85445 100644 --- a/live/Makefile +++ b/live/Makefile @@ -63,4 +63,7 @@ build: $(DESTDIR) $(MAKE) all (cd $(DESTDIR) && osc -A $(OBS_API) build -M $(FLAVOR) $(OSC_OPTS) $(OBS_TARGET) $(ARCH) $(KIWI_FILE)) +check: + for i in ./test/*_test.*; do $${i}; done + .PHONY: build all clean diff --git a/live/README.md b/live/README.md index e04e90f79e..c24446fe7f 100644 --- a/live/README.md +++ b/live/README.md @@ -40,6 +40,7 @@ This directory contains a set of files that are used to build the Agama Live ISO a separate [PXE documentation](PXE.md) for more details about the PXE boot - [config-cdroot](config-cdroot) subdirectory contains file which are copied to the uncompressed root of the ISO image, the files can be accessed just by mounting the ISO file or the DVD medium +- [test](test) subdirectory contains tests to verify correctness of content. Can be run with `make check` ## Building the sources diff --git a/live/root/etc/systemd/system/agama-cmdline-process.service b/live/root/etc/systemd/system/agama-cmdline-process.service new file mode 100644 index 0000000000..661d6166f8 --- /dev/null +++ b/live/root/etc/systemd/system/agama-cmdline-process.service @@ -0,0 +1,21 @@ +[Unit] +Description=Agama kernel cmdline processing + +# have to be after network to be able to download info files +# TODO: what to do in air gap scenario where we still need process cmdline? +After=network-online.target + +# before starting the Agama servers so they read configuration parsed +Before=agama-web-server.service +Before=agama.service +Before=x11-autologin.service + +[Service] +Type=oneshot +Environment=TERM=linux +ExecStart=agama-kernel-cmdline.sh +StandardInput=tty +TimeoutSec=0 + +[Install] +WantedBy=default.target diff --git a/live/root/etc/systemd/system/agama-self-update.service b/live/root/etc/systemd/system/agama-self-update.service index 5d80b9ef55..820cf16f10 100644 --- a/live/root/etc/systemd/system/agama-self-update.service +++ b/live/root/etc/systemd/system/agama-self-update.service @@ -3,6 +3,9 @@ Description=Agama self-update After=network-online.target +# and after we process agama params like info which can contain password +After=agama-cmdline-process.service + # before starting the Agama servers so they use the new packages Before=agama-web-server.service Before=agama.service @@ -11,11 +14,6 @@ Before=x11-autologin.service Before=live-password-dialog.service Before=live-password-systemd.service -# kernel command line option -ConditionKernelCommandLine=|agama.self_update -# linuxrc/YaST backward compatibility -ConditionKernelCommandLine=|agama.selfupdate - [Service] Type=oneshot Environment=TERM=linux diff --git a/live/root/etc/systemd/system/live-password-cmdline.service b/live/root/etc/systemd/system/live-password-cmdline.service index 3307967f7b..f2b183a3a0 100644 --- a/live/root/etc/systemd/system/live-password-cmdline.service +++ b/live/root/etc/systemd/system/live-password-cmdline.service @@ -9,9 +9,8 @@ Before=agama-web-server.service Before=live-password-dialog.service Before=live-password-systemd.service -# plain text password or hashed password passed via kernel command line -ConditionKernelCommandLine=|live.password -ConditionKernelCommandLine=|live.password_hash +# and after we process agama params like info which can contain password +After=agama-cmdline-process.service [Service] ExecStart=live-password --kernel diff --git a/live/root/etc/systemd/system/live-password-dialog.service b/live/root/etc/systemd/system/live-password-dialog.service index f463684ce1..5bde8e9584 100644 --- a/live/root/etc/systemd/system/live-password-dialog.service +++ b/live/root/etc/systemd/system/live-password-dialog.service @@ -22,8 +22,8 @@ Before=serial-getty@ttyS1.service Before=serial-getty@ttyS2.service Before=serial-getty@ttysclp0.service -# kernel command line option -ConditionKernelCommandLine=live.password_dialog +# and after we process agama params like info which can contain kernel parameters +After=agama-cmdline-process.service [Service] Type=oneshot diff --git a/live/root/etc/systemd/system/live-password-systemd.service b/live/root/etc/systemd/system/live-password-systemd.service index eb81bae6c3..8aef371671 100644 --- a/live/root/etc/systemd/system/live-password-systemd.service +++ b/live/root/etc/systemd/system/live-password-systemd.service @@ -22,8 +22,8 @@ Before=serial-getty@ttyS1.service Before=serial-getty@ttyS2.service Before=serial-getty@ttysclp0.service -# kernel command line option -ConditionKernelCommandLine=live.password_systemd +# and after we process agama params like info which can contain kernel parameters +After=agama-cmdline-process.service [Service] Type=oneshot diff --git a/live/root/usr/bin/agama-kernel-cmdline.sh b/live/root/usr/bin/agama-kernel-cmdline.sh new file mode 100755 index 0000000000..28711db05f --- /dev/null +++ b/live/root/usr/bin/agama-kernel-cmdline.sh @@ -0,0 +1,4 @@ +#! /bin/sh + +kernel-cmdline-conf.sh +info-cmdline-conf.sh diff --git a/live/root/usr/bin/agama-self-update b/live/root/usr/bin/agama-self-update index e1958571f5..2b98aa8fe3 100755 --- a/live/root/usr/bin/agama-self-update +++ b/live/root/usr/bin/agama-self-update @@ -5,6 +5,10 @@ # This script updates the Agama packages in the Live system from the # Agama Devel OBS project. +# check if self-update is required +if ! grep -q "[[:space:]^]agama.self_update=1\([[:space:]]\|$\)" /run/agama/cmdline.d/agama.conf; then + exit 0 +fi # first try a quick and simple solution, refreshing the distributions repository takes a # lot of time so try using only the agama-devel for update diff --git a/live/root/usr/bin/info-cmdline-conf.sh b/live/root/usr/bin/info-cmdline-conf.sh new file mode 100755 index 0000000000..b44b4b024d --- /dev/null +++ b/live/root/usr/bin/info-cmdline-conf.sh @@ -0,0 +1,28 @@ +#! /bin/sh + +# Script that expand agama.info parameter by downloading its file and appending it to agama.conf +# the info content is stored in info.conf + +set -e + +TARGET="${1:-/run/agama/cmdline.d/agama.conf}" +INFO_CONTENT="${2:-/run/agama/cmdline.d/info.conf}" + +expand_info_arg() { + INFO_URL=$(sed -n 's/\(.*[[:space:]]\|^\)agama\.info=\([^[:space:]]\+\).*/\2/p' "$TARGET") + if [ -z "${INFO_URL}" ]; then + return 0 + fi + + # TODO: should we use also --location-trusted if info file url contain user and password? + # if so check with security team + curl --location --silent "${INFO_URL}" > "${INFO_CONTENT}" + # remove info param + sed -in 's/\([[:space:]]\|^\)agama\.info=[^[:space:]]\+//' "${TARGET}" + # and add content of info file + cat "${INFO_CONTENT}" >> "${TARGET}" + + return 0 +} + +expand_info_arg diff --git a/live/root/usr/bin/kernel-cmdline-conf.sh b/live/root/usr/bin/kernel-cmdline-conf.sh new file mode 100755 index 0000000000..a34ea9a620 --- /dev/null +++ b/live/root/usr/bin/kernel-cmdline-conf.sh @@ -0,0 +1,34 @@ +#! /bin/sh + +# Script to clean kernel command line from agama specific parameters. Result is later used for bootloader proposal. + +SOURCE="${1:-/proc/cmdline}" +TARGET="${2:-/run/agama/cmdline.d/kernel.conf}" + +write_kernel_args() { + DIR=$(dirname "${TARGET}") + mkdir -p "$DIR" + # ensure that kernel cmdline line is created to avoid reading agama params + # if there is no kernel params + touch "${TARGET}" + + for _i in $(cat "${SOURCE}"); do + case ${_i} in + # remove all agama kernel params + # Add here also all linuxrc supported parameters + LIBSTORAGE_* | YAST_* | agama* | Y2* | ZYPP_* | autoyast* ) + _found=1 + ;; + esac + + if [ -z "$_found" ]; then + echo "Non-Agama parameter found ($_i)" + echo -n " $_i" >>"${TARGET}" + fi + unset _found + done + + return 0 +} + +write_kernel_args diff --git a/live/root/usr/bin/live-password b/live/root/usr/bin/live-password index 76ebf390d9..7b64989e59 100755 --- a/live/root/usr/bin/live-password +++ b/live/root/usr/bin/live-password @@ -27,6 +27,11 @@ msg_box() { } ask_password() { + # check if user wants dialog password + if ! grep -q "[[:space:]^]live.password_dialog=1\([[:space:]]\|$\)" /run/agama/cmdline.d/agama.conf; then + exit 0 + fi + if ! PWD1=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Password:" 8 40); then confirm_exit ask_password @@ -36,7 +41,7 @@ ask_password() { confirm_exit ask_password fi - + if [ "$PWD1" != "$PWD2" ]; then msg_box "Passwords do not match.\nPlease try again." ask_password @@ -51,6 +56,10 @@ ask_password() { # functions for entering the password using the "systemd-ask-password" tool ask_password_systemd() { + # check if user wants systemd password + if ! grep -q "[[:space:]^]live.password_systemd=1\([[:space:]]\|$\)" /run/agama/cmdline.d/agama.conf; then + exit 0 + fi if ! PWD1=$(systemd-ask-password --timeout=0 "Set login password: "); then exit 1 fi @@ -141,13 +150,14 @@ random_password() { } if [ "$1" = "--kernel" ]; then - # get the password from the kernel command line - PWD=$(awk -F 'live.password=' '{sub(/ .*$/, "", $2); print $2}' < /proc/cmdline) + # get the password from the kernel command line. It can contain newlines + PWD=$(grep 'live.password=' < /run/agama/cmdline.d/agama.conf | awk -F 'live.password=' '{sub(/ .*$/, "", $2); print $2}') if [ -n "$PWD" ]; then echo "$PWD" | passwd --stdin fi - PWD=$(awk -F 'live.password_hash=' '{sub(/ .*$/, "", $2); print $2}' < /proc/cmdline) + # get the password hash from the kernel command line. It can contain newlines + PWD=$(grep 'live.password_hash=' < /run/agama/cmdline.d/agama.conf | awk -F 'live.password_hash=' '{sub(/ .*$/, "", $2); print $2}') if [ -n "$PWD" ]; then usermod -p "$PWD" root fi diff --git a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/README b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/README index 2787db46c2..5d32a1ab7e 100644 --- a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/README +++ b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/README @@ -4,3 +4,20 @@ dracut agama-cmdline module This module writes any agama configuration given through the kernel cmdline to its own cmdline conf file copying it to the sysroot. +It also tries to translate the linuxrc ifcfg kernel cmdline argument to the +corresponding ip one but only basic scenarios are supported. + +## Supported examples + + ifcfg=*=dhcp + ip=dhcp + + ifcfg=eth0=dhcp + ip=eth0:dhcp + + ifcfg=eth0.10=192.168.0.100/24,192.168.0.1 + vlan=eth0.10:eth0 ip=192.168.0.100::192.168.0.1:24::eth0.10 + + ifcfg="eth0=192.168.0.33/24 10.0.0.100/24,192.168.0.1,192.168.0.1 10.0.0.1,suse.de" + ip=192.168.0.33::192.168.0.1:24::eth0 nameserver=192.168.0.1 nameserver=10.0.0.1 ip=10.0.0.100:::24::eth0 + diff --git a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/agama-network-compat.sh b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/agama-network-compat.sh new file mode 100755 index 0000000000..8a54c182c4 --- /dev/null +++ b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/agama-network-compat.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +[ -e /dracut-state.sh ] && . /dracut-state.sh + +. /lib/dracut-lib.sh +. /lib/net-lib.sh + +ifcfg_to_ip() { + local ip + local v="${2}", + local interface="$1" + local conf_path="/etc/cmdline.d/40-agama-network.conf" + set -- + while [ -n "$v" ]; do + set -- "$@" "${v%%,*}" + v=${v#*,} + done + + ### See https://en.opensuse.org/SDB:Linuxrc#Network_Config + # ifcfg==[try,]dhcp*,[rfc2132,]OPTION1=value1,OPTION2=value2... + if str_starts "$1" "dhcp"; then + autoconf="$1" + if [ "$autoconf" = "dhcp4" ]; then + autoconf="dhcp" + fi + case $autoconf in + "dhcp" | "dhcp6") + if [ "$interface" = "*" ]; then + echo "ip=${1}" >>$conf_path + + else + echo "ip=${interface}:${1}" >>$conf_path + fi + ;; + *) + echo "No supported option ${1}" + ;; + esac + + return 0 + fi + + # ifcifg==ip,gateway,nameserver,domain + if strglob "$1" "*.*.*.*/*"; then + [[ -n "$2" ]] && gateway=$2 + [[ -n "$3" ]] && nameserver=$3 + + ip="$1 " + set -- + while [ -n "$ip" ]; do + set -- "$@" "${ip%% *}" + ip="${ip#* }" + done + + ## TODO: IP is a LIST_IP + ip="$1" + mask=${ip##*/} + ip=${ip%%/*} + shift + + ## Configure the first interface, the gateway must belong to the same network + echo "ip=${ip}::${gateway}:$mask::${interface}" >>$conf_path + + ## Configure multiple addresses for the same interface + while [[ $# -gt 0 ]]; do + ip="$1" + mask=${ip##*/} + ip=${ip%%/*} + echo "ip=${ip}:::$mask::${interface}" >>$conf_path + shift + done + + ## Configure nameservers + if [[ -n $nameserver ]]; then + nameserver="$nameserver " + while [ -n "$nameserver" ]; do + echo "nameserver=${nameserver%% *}" >>$conf_path + nameserver="${nameserver#* }" + done + fi + fi + + return 0 +} + +translate_ifcfg() { + local i + local vlan + local phydevice + local conf_path="/etc/cmdline.d/40-agama-network.conf" + + while read -r i; do + set -- + echo "### Processing $i ###" + set -- "$@" "${i%%=*}" + options="${i#*=}" + pattern="$1" + unset vlan phydevice + + if str_starts "$options" "try,"; then + options="${i#*try,*}" + fi + + # The pattern Looks like a VLAN like eth0.10 + if strglobin "$pattern" "*.[0-9]*"; then + phydevice=${pattern%.*} + vlan="vlan=$1:$phydevice" + echo "$vlan" >>$conf_path + fi + + # Try to translate the pattern as it is, we cannot try to apply the config to check if + # it is valid because the nm-initrd-generator is called by a cmdline hook unless we call + # explicitly passing the getcmdline result + ifcfg_to_ip "$pattern" "$options" + + set -- + unset options pattern CMDLINE + done <<<"$(getargs ifcfg)" + + return 0 +} + +translate_ifcfg diff --git a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/module-setup.sh b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/module-setup.sh index 24a6bcd321..a25645c0f0 100755 --- a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/module-setup.sh +++ b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/module-setup.sh @@ -17,5 +17,6 @@ installkernel() { # called by dracut install() { inst_hook cmdline 99 "$moddir/agama-cmdline-conf.sh" + inst_hook cmdline 99 "$moddir/agama-network-compat.sh" inst_hook pre-pivot 99 "$moddir/save-agama-conf.sh" } diff --git a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/save-agama-conf.sh b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/save-agama-conf.sh index 612843ddd7..510a14b4f2 100755 --- a/live/root/usr/lib/dracut/modules.d/99agama-cmdline/save-agama-conf.sh +++ b/live/root/usr/lib/dracut/modules.d/99agama-cmdline/save-agama-conf.sh @@ -6,6 +6,6 @@ if [ -e /etc/cmdline.d/99-agama-cmdline.conf ]; then echo "Creating agama conf" - mkdir -p "$NEWROOT/etc/agama.d" - cp /etc/cmdline.d/99-agama-cmdline.conf "$NEWROOT/etc/agama.d/cmdline.conf" + mkdir -p "$NEWROOT/run/agama/cmdline.d" + cp /etc/cmdline.d/99-agama-cmdline.conf "$NEWROOT/run/agama/cmdline.d/agama.conf" fi diff --git a/live/src/agama-installer.changes b/live/src/agama-installer.changes index 5c57bfe509..d7cea96900 100644 --- a/live/src/agama-installer.changes +++ b/live/src/agama-installer.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Wed Feb 19 08:49:24 UTC 2025 - Knut Anderssen + +- Added support for giving a file URL with extra kernel cmdline + arguments (agama.info) which was known as the info file in + linuxrc. +- Added basic support for translating the ifcfg kernel cmdline arg + to its ip equivalent (gh#agama-project/agama#1896). +- Moved the kernel cmdline conf under /run/agama/cmdline.d + ------------------------------------------------------------------- Wed Feb 19 07:37:51 UTC 2025 - Ladislav Slezák diff --git a/live/src/config.sh b/live/src/config.sh index f7e2920ad1..9fdf7efe56 100644 --- a/live/src/config.sh +++ b/live/src/config.sh @@ -44,6 +44,7 @@ systemctl enable agama-hostname.service systemctl enable agama-proxy-setup.service systemctl enable agama-certificate-issue.path systemctl enable agama-certificate-wait.service +systemctl enable agama-cmdline-process.service systemctl enable agama-welcome-issue.service systemctl enable agama-avahi-issue.service systemctl enable agama-url-issue.service diff --git a/live/test/fixtures/expected/cmdline b/live/test/fixtures/expected/cmdline new file mode 100644 index 0000000000..d07b617330 --- /dev/null +++ b/live/test/fixtures/expected/cmdline @@ -0,0 +1 @@ + BOOT_IMAGE=/boot/vmlinuz splash=silent mitigations=auto quiet nosimplefb=1 \ No newline at end of file diff --git a/live/test/fixtures/expected/info_cmdline b/live/test/fixtures/expected/info_cmdline new file mode 100644 index 0000000000..ca2bb594ab --- /dev/null +++ b/live/test/fixtures/expected/info_cmdline @@ -0,0 +1,3 @@ +BOOT_IMAGE=/boot/vmlinuz splash=silent nosimplefb=1 +agama.install_url=ftp://test.com/repo +live.password=secret \ No newline at end of file diff --git a/live/test/fixtures/expected/info_cmdline.info b/live/test/fixtures/expected/info_cmdline.info new file mode 100644 index 0000000000..9de6db162f --- /dev/null +++ b/live/test/fixtures/expected/info_cmdline.info @@ -0,0 +1,2 @@ +agama.install_url=ftp://test.com/repo +live.password=secret \ No newline at end of file diff --git a/live/test/fixtures/source/cmdline b/live/test/fixtures/source/cmdline new file mode 100644 index 0000000000..d43325ea28 --- /dev/null +++ b/live/test/fixtures/source/cmdline @@ -0,0 +1 @@ +BOOT_IMAGE=/boot/vmlinuz splash=silent agama.auto=ftp://example.suse.cz/profile.json LIBSTORAGE_MULTIPATH=1 mitigations=auto Y2DEBUG=1 quiet nosimplefb=1 diff --git a/live/test/fixtures/source/info_cmdline b/live/test/fixtures/source/info_cmdline new file mode 100644 index 0000000000..32aeff0894 --- /dev/null +++ b/live/test/fixtures/source/info_cmdline @@ -0,0 +1 @@ +BOOT_IMAGE=/boot/vmlinuz splash=silent agama.info=https://pastebin.com/raw/krzAVL8S nosimplefb=1 diff --git a/live/test/info_cmdline_test.rb b/live/test/info_cmdline_test.rb new file mode 100755 index 0000000000..93c1672c0d --- /dev/null +++ b/live/test/info_cmdline_test.rb @@ -0,0 +1,51 @@ +#! /usr/bin/rspec +require "tmpdir" + +describe "info-cmdline-conf.sh" do + let(:script_path) { File.expand_path("../root/usr/bin/info-cmdline-conf.sh", __dir__, ) } + + context "There is no info parameter" do + let(:source_path) { File.expand_path("fixtures/source/cmdline", __dir__, ) } + let(:expected_path) { File.expand_path("fixtures/source/cmdline", __dir__, ) } + + + it "does nothing" do + Dir.mktmpdir do |tmpdir| + target_path = File.join(tmpdir, "cmdline") + FileUtils.cp(source_path, target_path) + info_path = File.join(tmpdir, "cmdline.info") + command = "#{script_path} #{target_path} #{info_path}" + cmd_result = system(command) + expect(cmd_result).to eq true + expected = File.read(expected_path) + result = File.read(target_path) + expect(result).to eq expected + expect(File.exists?(info_path)).to eq false + end + end + end + + context "There is info parameter" do + let(:source_path) { File.expand_path("fixtures/source/info_cmdline", __dir__, ) } + let(:expected_path) { File.expand_path("fixtures/expected/info_cmdline", __dir__, ) } + let(:expected_info_path) { File.expand_path("fixtures/expected/info_cmdline.info", __dir__, ) } + + it "removes info parameter and add its content" do + Dir.mktmpdir do |tmpdir| + target_path = File.join(tmpdir, "cmdline") + FileUtils.cp(source_path, target_path) + info_path = File.join(tmpdir, "cmdline.info") + command = "#{script_path} #{target_path} #{info_path}" + cmd_result = system(command) + expect(cmd_result).to eq true + expected = File.read(expected_path) + result = File.read(target_path) + expect(result).to eq expected + + expected_info = File.read(expected_info_path) + result_info = File.read(info_path) + expect(result_info).to eq expected_info + end + end + end +end diff --git a/live/test/kernel_cmdline_test.rb b/live/test/kernel_cmdline_test.rb new file mode 100755 index 0000000000..ce2c1e8258 --- /dev/null +++ b/live/test/kernel_cmdline_test.rb @@ -0,0 +1,19 @@ +#! /usr/bin/rspec +require "tmpdir" + +describe "kernel-cmdline-conf.sh" do + it "filters out any agama params" do + script_path = File.expand_path("../root/usr/bin/kernel-cmdline-conf.sh", __dir__, ) + source_path = File.expand_path("fixtures/source/cmdline", __dir__, ) + expected_path = File.expand_path("fixtures/expected/cmdline", __dir__, ) + tmpdir = Dir.mktmpdir do |tmpdir| + target_path = File.join(tmpdir, "cmdline") + command = "#{script_path} #{source_path} #{target_path}" + cmd_result = system(command) + expect(cmd_result).to eq true + expected = File.read(expected_path) + result = File.read(target_path) + expect(result).to eq expected + end + end +end diff --git a/service/lib/agama/cmdline_args.rb b/service/lib/agama/cmdline_args.rb index 963abf401e..778cde2e45 100644 --- a/service/lib/agama/cmdline_args.rb +++ b/service/lib/agama/cmdline_args.rb @@ -22,7 +22,6 @@ module Agama # This class is responsible for reading Agama kernel cmdline options class CmdlineArgs - CMDLINE_PATH = "/proc/cmdline" CMDLINE_PREFIX = "agama." attr_accessor :config_url @@ -36,14 +35,16 @@ def initialize(data = {}) end def self.read - read_from("/proc/cmdline") + read_from("/run/agama/cmdline.d/agama.conf") end # Reads the kernel command line options def self.read_from(path) - options = File.read(path) args = new({}) + return args unless File.exist?(path) + + options = File.read(path) options.split.each do |option| next unless option.start_with?(CMDLINE_PREFIX) diff --git a/service/lib/agama/config_reader.rb b/service/lib/agama/config_reader.rb index debad5b1c1..35912ee826 100644 --- a/service/lib/agama/config_reader.rb +++ b/service/lib/agama/config_reader.rb @@ -117,7 +117,7 @@ def copy_file(location, target) # @return [CmdlineArgs] def cmdline_args - @cmdline_args ||= CmdlineArgs.read_from(File.join(workdir, "/proc/cmdline")) + @cmdline_args ||= CmdlineArgs.read_from(File.join(workdir, "/run/agama/cmdline.d/agama.conf")) end # return [Config] diff --git a/service/lib/agama/software/product_builder.rb b/service/lib/agama/software/product_builder.rb index 1f1888ee24..f5422e0bbf 100644 --- a/service/lib/agama/software/product_builder.rb +++ b/service/lib/agama/software/product_builder.rb @@ -37,7 +37,7 @@ def initialize(config, logger: Logger.new($stdout)) # # @return [Array] def build - cmdline_args = CmdlineArgs.read_from("/proc/cmdline") + cmdline_args = CmdlineArgs.read_from("/run/agama/cmdline.d/agama.conf") @logger.info cmdline_args config.products.map do |id, attrs| data = product_data_from_config(id) diff --git a/service/test/agama/cmdline_args_test.rb b/service/test/agama/cmdline_args_test.rb index fee3a392f8..201848b743 100644 --- a/service/test/agama/cmdline_args_test.rb +++ b/service/test/agama/cmdline_args_test.rb @@ -28,28 +28,28 @@ describe ".read_from" do it "reads the kernel command line options and return a CmdlineArgs object" do - args = described_class.read_from(File.join(workdir, "/proc/cmdline")) + args = described_class.read_from(File.join(workdir, "/run/agama/cmdline.d/agama.conf")) expect(args.data["auto"]).to eq("http://mydomain.org/tumbleweed.jsonnet") end it "sets #config_url if specified on cmdline" do - args = described_class.read_from(File.join(workdir, "/proc/cmdline")) + args = described_class.read_from(File.join(workdir, "/run/agama/cmdline.d/agama.conf")) expect(args.config_url).to eql("http://example.org/agama.yaml") end it "converts 'true' and 'false' values into booleans" do - args = described_class.read_from(File.join(workdir, "/proc/cmdline")) + args = described_class.read_from(File.join(workdir, "/run/agama/cmdline.d/agama.conf")) expect(args.data["web"]).to eql({ "ssl" => true }) end it "converts keys with dots after 'agama.' to hash" do - args = described_class.read_from(File.join(workdir, "/proc/cmdline")) + args = described_class.read_from(File.join(workdir, "/run/agama/cmdline.d/agama.conf")) # here fixture has agama.web.ssl=true and result is this hash expect(args.data["web"]).to eq({ "ssl" => true }) end it "properly parse values that contain '='" do - args = described_class.read_from(File.join(workdir, "/proc/cmdline")) + args = described_class.read_from(File.join(workdir, "/run/agama/cmdline.d/agama.conf")) expect(args.data["install_url"]).to eq("cd:/?devices=/dev/sr1") end end diff --git a/service/test/fixtures/root_dir/proc/cmdline b/service/test/fixtures/root_dir/run/agama/cmdline.d/agama.conf similarity index 100% rename from service/test/fixtures/root_dir/proc/cmdline rename to service/test/fixtures/root_dir/run/agama/cmdline.d/agama.conf