#!/bin/bash
# kola: { "timeoutMin": 20 }
#
# Copyright (C) 2021 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

set -euo pipefail

. ${KOLA_EXT_DATA}/libtest.sh

set -x

libtest_prepare_offline
cd $(mktemp -d)

# TODO: It'd be much better to test this via a registry
image_dir=/var/tmp/fcos
image=oci:$image_dir
image_pull=ostree-unverified-image:$image
tmp_imagedir=/var/tmp/fcos-tmp
arch=$(arch)

case "${AUTOPKGTEST_REBOOT_MARK:-}" in
  "")
    # Take the existing ostree commit, and export it to a container image, then rebase to it.

    checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum')
    v0=$(rpm-ostree status --json | jq -r '.deployments[0].version')
    rm ${image_dir} -rf
    
    # Since we're switching OS update stream, turn off zincati
    systemctl mask --now zincati

    rpm-ostree ex-container 'export' --repo=/ostree/repo ${checksum} "${image}"
    rpm-ostree rebase "$image_pull" --experimental | tee out.txt
    assert_file_has_content out.txt 'Importing.*'"$image_pull"
    rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:$image\""
    rpmostree_assert_status ".deployments[0][\"checksum\"] == \"${checksum}\""
    echo "ok rebase to container image reference"

    rpm-ostree status | tee out.txt
    assert_file_has_content_literal out.txt 'Digest: sha256:'
    ostree container image list --repo=/ostree/repo | tee imglist.txt
    assert_streq "$(wc -l < imglist.txt)" 1

    v1=$(rpm-ostree status --json | jq -r '.deployments[0].version')
    assert_streq "${v0}" "${v1}"

    # Test rebasing back to ostree https://github.com/coreos/rpm-ostree/issues/3677
    rpm-ostree rebase "$checksum"
    rpm-ostree rebase "$image_pull" --experimental

    /tmp/autopkgtest-reboot 1
    ;;
  1)
    # Add a new RPM via local layering, then export the new locally-generated commit as
    # a base image, then test upgrading to that.

    if rpm-ostree deploy 42 2>err.txt; then
        fatal "unexpectedly deployed version from container image reference"
    fi
    assert_file_has_content err.txt 'Cannot look up version while tracking a container image reference'
    echo "ok cannot deploy when tracking container image"

    # Test layering
    if rpm -q foo 2>/dev/null; then
      fatal "found foo"
    fi
    rpm-ostree install ${KOLA_EXT_DATA}/rpm-repos/0/packages/x86_64/foo-1.2-3.x86_64.rpm
    echo "ok layering package"

    # Test upgrade
    rpm-ostree upgrade | tee out.txt
    assert_file_has_content_literal out.txt "Pulling manifest: ${image_pull}"
    assert_file_has_content out.txt "No upgrade available."
    echo "ok no upgrade available"

    # Create a new ostree commit containing foo and export the commit as a container image
    with_foo_commit=$(rpm-ostree status --json | jq -r '.deployments[0].checksum')
    ostree refs ${with_foo_commit} --create vmcheck_tmp/new_update
    new_commit=$(ostree commit -b vmcheck --bootable --tree=ref=vmcheck_tmp/new_update)
    rm "${image_dir}" -rf
    rpm-ostree ex-container export --repo=/ostree/repo ${new_commit} "$image"

    rpm-ostree uninstall foo
    rpm-ostree upgrade
    rpmostree_assert_status ".deployments[0][\"checksum\"] == \"${new_commit}\""

    /tmp/autopkgtest-reboot 2
    ;;
  2)
    # Export the booted image again, but this time test layered containers via a `podman build`.

    rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"${image_pull}\""
    assert_streq $(rpm -q foo) foo-1.2-3.x86_64

    checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum')
    rm "${image_dir}" -rf
    rpm-ostree ex-container 'export' --repo=/ostree/repo ${checksum} "${image}"
    # https://github.com/ostreedev/ostree-rs-ext/issues/153
    skopeo copy $image containers-storage:localhost/fcos
    rm "${image_dir}" -rf
    td=$(mktemp -d)
    cd ${td}
    arch=$(arch)
    # TODO close race here around webserver readiness
    (cd ${KOLA_EXT_DATA}/rpm-repos/0 && ~core/kolet httpd) &
    while ! curl -q http://127.0.0.1; do sleep 1; done
    cat >local.repo << 'EOF'
[local]
gpgcheck=0
baseurl=http://127.0.0.1
EOF
    cat >baz.yaml << 'EOF'
packages:
  - baz-1.0
  - boo-1.0
EOF
    cat >testdaemon-query.yaml << 'EOF'
repo-packages:
  - repo: local
    packages:
      - testdaemon
EOF
    cat >nonano.yaml << 'EOF'
override-remove:
  - nano
  - nano-default-editor
EOF
    cp ${KOLA_EXT_DATA}/rpm-repos/0/packages/x86_64/baz-2.0-1.x86_64.rpm .
    baz_chksum=$(sha256sum baz-2.0-1.x86_64.rpm | cut -f1 -d' ')
    cat >replace-baz.yaml <<EOF
override-replace-local:
  baz-2.0-1.x86_64: ${baz_chksum}
ex-override-replace:
  - from:
      repo: local
    packages:
      - boo
EOF
cat > Dockerfile << EOF
FROM localhost/fcos
RUN rm -rf /etc/yum.repos.d/*  # Ensure we work offline
ADD local.repo /etc/yum.repos.d/
RUN rpm-ostree install bar
RUN mkdir -p /etc/rpm-ostree/origin.d
ADD baz.yaml testdaemon-query.yaml nonano.yaml /etc/rpm-ostree/origin.d/
RUN rpm-ostree ex rebuild
ADD replace-baz.yaml /etc/rpm-ostree/origin.d/
ADD baz-2.0-1.x86_64.rpm /run/rpm-ostree/staged-rpms/${baz_chksum}.rpm
RUN rpm-ostree ex rebuild
RUN echo some config file > /etc/someconfig.conf
RUN echo somedata > /usr/share/somenewdata
# Verify we're ignoring subdirectories that don't contain vmlinuz https://github.com/coreos/rpm-ostree/issues/3965
RUN mkdir -p /usr/lib/modules/blah && touch /usr/lib/modules/blah/foo
RUN rpm-ostree cleanup -m
EOF
    # Older podman found in RHEL8 blows up without /etc/resolv.conf
    # which happens in our qemu path.
    touched_resolv_conf=0
    if test '!' -f /etc/resolv.conf; then
      podmanv=$(podman --version)
      case "${podmanv#podman version }" in
        3.*) touched_resolv_conf=1; touch /etc/resolv.conf;;
      esac
    fi
    podman build --net=host -t localhost/fcos-derived --squash .
    if test "${touched_resolv_conf}" -eq 1; then
      rm -vf /etc/resolv.conf
    fi
    derived=oci:$image_dir:derived
    skopeo copy containers-storage:localhost/fcos-derived $derived
    rpm-ostree rebase --experimental ostree-unverified-image:$derived
    ostree container image list --repo=/ostree/repo | tee imglist.txt
    assert_streq "$(wc -l < imglist.txt)" 1
    rm $image_dir -rf
    /tmp/autopkgtest-reboot 3
    ;;
  3) 
    grep -qF 'some config file' /etc/someconfig.conf || (echo missing someconfig.conf; exit 1)
    grep -qF somedata /usr/share/somenewdata || (echo missing somenewdata; exit 1)
    for p in bar testdaemon; do
      assert_streq $(rpm -q $p) $p-1.0-1.${arch}
      test -f /usr/bin/$p
    done
    assert_streq $(rpm -q baz) baz-2.0-1.${arch}
    test -f /usr/bin/baz
    ! rpm -q nano
    rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:derived\""
    ;;
  *) echo "unexpected mark: ${AUTOPKGTEST_REBOOT_MARK}"; exit 1;;
esac
