#!/usr/bin/env atf-sh # vim:set filetype=sh: # shellcheck shell=sh . $(atf_get_srcdir)/test_env.sh export PREFIX="$srcdir" export MOCK=echo export CLOUD=nocloud init_tests \ set_ephemeral_network_cmdline \ set_network_config_network_interfaces \ set_network_config_auto \ userdata_user_name \ userdata_user_missing_name \ userdata_create_default_user \ userdata_no_default_user \ userdata_users_default_user \ userdata_users_default_name_only \ userdata_users_name_only \ userdata_users_gecos \ userdata_users_homedir \ userdata_users_shell \ userdata_users_primary_group \ userdata_users_system \ userdata_users_no_create_home \ userdata_users_groups \ userdata_users_lock_passwd \ userdata_users_doas \ userdata_users_ssh_authorized_keys \ userdata_ssh_authorized_keys \ userdata_groups \ userdata_bootcmd \ userdata_write_files \ userdata_ntp \ userdata_ntp_busybox \ userdata_ntp_openntpd \ userdata_apk_cache \ userdata_apk_empty \ userdata_apk_repositories \ userdata_apk_repositories_version \ userdata_apk_repositories_version_auto_edge \ userdata_package_update \ userdata_package_upgrade \ userdata_packages \ userdata_runcmd \ userdata_autoinstall set_ephemeral_network_cmdline_body() { fake_interfaces eth0 eth1 eth2 echo up > sys/class/net/eth1/operstate mkdir -p proc echo "ds=nocloud;h=foo;seedfrom=https://example.tld" > proc/cmdline atf_check \ -o match:"udhcpc.*eth1" \ -e match:"set_ephemeral_network: done" \ tiny-cloud boot } set_network_config_network_interfaces_body() { fake_metadata_nocloud <<-EOF network-interfaces: | auto eth1 iface eth1 address 192.168.100.1 netmask 255.255.255.0 resolv_conf: nameservers: - 8.8.8.8 - 8.8.4.4 EOF atf_check \ -o match:"rc-update" \ -e match:"set_network_interfaces: done" \ tiny-cloud boot atf_check \ -o match:"auto eth1" \ -o match:"iface eth1" \ -o match:"address 192.168.100.1" \ cat etc/network/interfaces atf_check \ -o match:"^nameserver 8.8.8.8$" \ -o match:"^nameserver 8.8.4.4$" \ cat etc/resolv.conf } set_network_config_auto_body() { fake_metadata_nocloud <<-EOF resolv_conf: nameservers: - 8.8.8.8 - 8.8.4.4 EOF fake_interfaces eth0 eth1 eth2 echo up > sys/class/net/eth1/operstate atf_check \ -o match:"rc-update" \ -e match:"set_network_interfaces: done" \ tiny-cloud boot atf_check \ -o match:"auto eth1" \ -o match:"iface eth1" \ -o match:"use dhcp" \ cat etc/network/interfaces # resolv.conf should be ignored with dhcp if [ -e etc/resolv.conf ]; then atf_fail "etc/resolv.conf should not been created with DHCP" fi } userdata_user_name_body() { fake_userdata_nocloud <<-EOF #alpine-config user: name: joeuser EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"create_default_user: done" \ -o match:"adduser.*joeuser" \ tiny-cloud main } userdata_user_missing_name_body() { fake_userdata_nocloud <<-EOF #alpine-config user: gecos: Foo B. Baz EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"create_default_user: done" \ -o not-match:"adduser.*gecos" \ tiny-cloud main } userdata_create_default_user_body() { fake_userdata_nocloud <<-EOF #alpine-config EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"create_default_user: done" \ -o match:"adduser.*alpine" \ tiny-cloud main } userdata_no_default_user_body() { fake_userdata_nocloud <<-EOF #alpine-config users: [] EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"create_default_user: done" \ -o not-match:"adduser" \ tiny-cloud main } userdata_users_default_user_body() { fake_userdata_nocloud <<-EOF #alpine-config users: - default EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"create_default_user: done" \ -o match:"adduser.*alpine" \ tiny-cloud main } userdata_users_default_name_only_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - name: foo EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*foo" \ -o match:"chpasswd -e" \ tiny-cloud main } userdata_users_name_only_body() { fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*foo" \ tiny-cloud main } userdata_users_gecos_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo gecos: Joe User EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*-g Joe User.*foo" \ tiny-cloud main } userdata_users_homedir_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo homedir: /foo EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*-h /foo.*foo" \ tiny-cloud main } userdata_users_shell_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo shell: /bin/zsh EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*-s /bin/zsh.*foo" \ tiny-cloud main } userdata_users_primary_group_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo primary_group: wheel EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*-G wheel.*foo" \ tiny-cloud main } userdata_users_system_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo system: true EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*-S.*foo" \ tiny-cloud main } userdata_users_no_create_home_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo no_create_home: true EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"adduser.*-H.*foo" \ tiny-cloud main } userdata_users_groups_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: foo groups: wheel, admin EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o match:"addgroup.*foo.*wheel" \ -o match:"addgroup.*foo.*admin" \ tiny-cloud main } userdata_users_lock_passwd_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - none - name: foo lock_passwd: false EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o not-match:"chpasswd -e" \ tiny-cloud main } userdata_users_doas_body() { # first specified user will replace default user fake_userdata_nocloud <<-EOF #alpine-config users: - none - name: foo doas: ["permit nopass foo"] EOF mkdir -p etc/doas.d atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_users: done" \ -o ignore \ tiny-cloud main find . grep "permit nopass foo" etc/doas.d/foo.conf \ || atf_fail "etc/doas.d/foo.conf is not as expected" } userdata_users_ssh_authorized_keys_body() { fake_bin getent <<-EOF #!/bin/sh echo "root:x:1000:1000:Linux User,,,:/root:/bin/sh" EOF fake_userdata_nocloud <<-EOF #alpine-config users: - default - name: root ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIiHcbg/7ytfLFHUNLRgEAubFz/13SwXBOM/05GNZe4 user@example.com EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -o ignore \ -e match:"userdata_users: done" \ tiny-cloud main find cat root/.ssh/authorized_keys atf_check -o match:"ssh-ed25519.*user@example.com" \ grep ssh-ed25519 root/.ssh/authorized_keys } userdata_ssh_authorized_keys_body() { fake_bin getent <<-EOF #!/bin/sh echo "alpine:x:1000:1000:Linux User,,,:/home/alpine:/bin/sh" EOF fake_metadata_nocloud <<-EOF public-keys: - openssh-key: ssh-ed25519 keydata - openssh-key: ssh-rsa foobar EOF fake_userdata_nocloud <<-EOF #alpine-config ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIiHcbg/7ytfLFHUNLRgEAubFz/13SwXBOM/05GNZe4 user@example.com - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA609xjvHkN8mTBiyYF6pZxMJAdy+aNZzpv+gP2dpWivJwxO7Zb9yRX6s9OKmKEj3kKRg5KQHwknSncDQ3eCljzyyer2m7ewnrAY0BrNs10o+vJfq3tsb5kZN6rZzisneHEzi5aZhmjwTItX827OaVXmIWkVHpfEVf4hVn9PuIl4AS/xtPogA/4IJrHo+DshKMaqEgII9t+/zeOEuzrSDPXDRvht768iEzGov+T4xj2LGMas9Edm/Ka4xVb5nSDZKDtXaXwshGrOxctjLZCMhT15Jdww6btrl9VltF6BLy/AJ+F1MVBjBiCjyTqaHLkuHjVQpFq2osWlDr1FrSe/S2kw== joeuser@something EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -o ignore \ -e match:"ssh_authorized_keys: done" \ tiny-cloud main atf_check -o match:"ssh-ed25519 keydata" \ grep keydata home/alpine/.ssh/authorized_keys atf_check -o match:"ssh-ed25519.*user@example.com" \ grep ssh-ed25519 home/alpine/.ssh/authorized_keys atf_check -o match:"ssh-rsa.*joeuser@something" \ grep ssh-rsa home/alpine/.ssh/authorized_keys } userdata_bootcmd_body() { fake_userdata_nocloud <<-EOF #alpine-config bootcmd: - echo foo - echo bar EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_bootcmd: done" \ -o match:"^foo$" -o match:"^bar$" \ tiny-cloud main } userdata_groups_body() { fake_userdata_nocloud <<-EOF #alpine-config groups: - group1 - group2 EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_groups: done" \ -o match:"addgroup group1" -o match:"addgroup group2" \ tiny-cloud main } userdata_ntp_body() { fake_userdata_nocloud <<-EOF #alpine-config ntp: enabled: true EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_ntp: done" \ -o match:"apk add.*chrony" \ -o match:"rc-update .*chronyd" \ -o match:"rc-service .*chronyd" \ tiny-cloud main } userdata_ntp_busybox_body() { fake_userdata_nocloud <<-EOF #alpine-config ntp: enabled: true ntp_client: busybox EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_ntp: done" \ -o not-match:"apk add" \ -o match:"rc-update .*ntpd" \ -o match:"rc-service .*ntpd" \ tiny-cloud main } userdata_ntp_openntpd_body() { fake_userdata_nocloud <<-EOF #alpine-config ntp: enabled: true ntp_client: openntpd EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_ntp: done" \ -o match:"apk add.*openntpd" \ -o match:"rc-update .*openntpd" \ -o match:"rc-service .*openntpd" \ tiny-cloud main } userdata_apk_cache_body() { fake_userdata_nocloud <<-EOF #alpine-config apk: cache: /var/cache/apk EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_apk_cache: done" \ -o ignore \ tiny-cloud main atf_check -o match:"$PWD/var/cache/apk" readlink -f etc/apk/cache } userdata_apk_empty_body() { fake_userdata_nocloud <<-EOF #alpine-config EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_apk_repositories: done" \ -o match:"setup-apkrepos -1 -c" \ tiny-cloud main } userdata_apk_repositories_body() { fake_userdata_nocloud <<-EOF #alpine-config apk: repositories: - base_url: /srv/packages repos: [ "main", "community" ] EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_apk_repositories: done" \ -o ignore \ tiny-cloud main atf_check -o match:"^/srv/packages/main$" \ -o match:"^/srv/packages/community$" \ cat etc/apk/repositories } userdata_apk_repositories_version_body() { fake_userdata_nocloud <<-EOF #alpine-config apk: repositories: - base_url: https://cdn.alpinelinux.org/ version: edge repos: [ "main", "community" ] EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_apk_repositories: done" \ -o ignore \ tiny-cloud main atf_check -o match:"^https://cdn.alpinelinux.org/edge/main$" \ -o match:"^https://cdn.alpinelinux.org/edge/community$" \ cat etc/apk/repositories } userdata_apk_repositories_version_auto_edge_body() { fake_userdata_nocloud <<-EOF #alpine-config apk: repositories: - base_url: https://cdn.alpinelinux.org/ repos: [ "main", "community" ] EOF mkdir -p etc echo "VERSION_ID=3.18_alpha20230329" > etc/os-release atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_apk_repositories: done" \ -o ignore \ tiny-cloud main atf_check -o match:"^https://cdn.alpinelinux.org/edge/main$" \ -o match:"^https://cdn.alpinelinux.org/edge/community$" \ cat etc/apk/repositories } userdata_package_update_body() { fake_userdata_nocloud <<-EOF #alpine-config package_update: true EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_package_update: done" \ -o match:"apk update" \ tiny-cloud main } userdata_package_upgrade_body() { fake_userdata_nocloud <<-EOF #alpine-config package_upgrade: true EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_package_upgrade: done" \ -o match:"apk upgrade" \ tiny-cloud main } userdata_packages_body() { fake_userdata_nocloud <<-EOF #alpine-config packages: - tmux - vim EOF atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_packages: done" \ -o match:"apk add .*tmux" \ -o match:"apk add .*vim" \ tiny-cloud main } userdata_runcmd_body() { fake_userdata_nocloud <<-EOF #alpine-config runcmd: - echo foo - echo bar EOF # run net phase to extract the user data atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_runcmd: done" \ -o match:"^foo$" -o match:"^bar$" \ tiny-cloud final } userdata_write_files_body() { fake_userdata_nocloud <<-EOF #alpine-config write_files: - path: /etc/motd content: | Hello world - path: /etc/foo encoding: text/plain permissions: '0755' content: | Hello world - path: /etc/bar owner: foo:bar content: | Hello world - path: /etc/gzipped encoding: gzip content: !!binary | H4sIAAAAAAAAA/NIzcnJVyjPL8pJ4QIA1eA5twwAAAA= - path: /foo/bar/hello content: | Hello world - path: /foo/bar/appended content: | Hello - path: /foo/bar/appended append: true content: | world EOF # fetch user-data atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_write_files: done" \ -o match:"chown foo:bar.*etc/bar" \ -o match:"chown root:root.*etc/motd" \ tiny-cloud main if [ "$(cat etc/motd)" != "Hello world" ]; then atf_fail "content of etc/motd was not 'Hello world'" fi # check that etc/motd permissions are the defaults atf_check -o match:"644" stat -c %a etc/motd if [ "$(cat etc/foo)" != "Hello world" ]; then atf_fail "content of etc/foo was not 'Hello world'" fi atf_check -o match:"755" stat -c %a etc/foo if [ "$(cat etc/gzipped)" != "Hello world" ]; then atf_fail "content of etc/foo was not 'Hello world'" fi if [ "$(cat foo/bar/hello)" != "Hello world" ]; then atf_fail "content of foo/bar/hello was not 'Hello world'" fi atf_check diff -u foo/bar/appended - <<-EOF Hello world EOF } userdata_autoinstall_body() { fake_userdata_nocloud <<-EOF #alpine-config autoinstall: true EOF fake_bin blkid <<-EOF #!/bin/sh true EOF fake_disk nvme0n8 10000 fake_disk vda 20000 # run net phase to extract the user data atf_check -e ignore -o ignore tiny-cloud early atf_check \ -e match:"userdata_autoinstall: done" \ -o match:"setup-disk" \ tiny-cloud final }