Skip to content

Commit

Permalink
✨ Add bundles to post-install hooks (kairos-io#171)
Browse files Browse the repository at this point in the history
* 🤖 Add bundles and sysext test

* ✨ Exec bundles also after install

* 🤖 Adapt tests

* 🎨 Create dir only if doesn't exist

* 🎨 Return err on mount

* 🎨 Make bundle errors failure as an option

* 🎨 Minor fixups

* debug

* 🤖 Fix spec

* 🤖 Get correct version for bundle test

* 🎨 Fixups

* 🤖 systemd-sysext is available only on opensuse for now
  • Loading branch information
mudler authored Oct 2, 2022
1 parent 520ee5d commit e556d75
Show file tree
Hide file tree
Showing 12 changed files with 361 additions and 50 deletions.
31 changes: 27 additions & 4 deletions .github/workflows/image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,30 @@ jobs:
mkdir build
mv $ISO build/kairos.iso
./earthly.sh +datasource-iso --CLOUD_CONFIG=tests/assets/autoinstall.yaml
./earthly.sh +run-qemu-tests --FLAVOR=${{ matrix.flavor }} --FROM_ARTIFACTS=true
./earthly.sh +run-qemu-datasource-tests --FLAVOR=${{ matrix.flavor }}
qemu-bundles-tests:
needs:
- build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- flavor: "opensuse"
steps:
- uses: actions/checkout@v2
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: kairos-${{ matrix.flavor }}.iso.zip
- run: |
ls -liah
export ISO=$PWD/$(ls *.iso)
mkdir build
mv $ISO build/kairos.iso
./earthly.sh +prepare-bundles-tests
./earthly.sh +run-qemu-bundles-tests --FLAVOR=${{ matrix.flavor }}
qemu-reset-tests:
needs:
Expand All @@ -194,7 +217,7 @@ jobs:
mkdir build
mv $ISO build/kairos.iso
./earthly.sh +datasource-iso --CLOUD_CONFIG=tests/assets/autoinstall.yaml
./earthly.sh +run-qemu-tests --TEST_SUITE=reset-test --FLAVOR=${{ matrix.flavor }} --FROM_ARTIFACTS=true
./earthly.sh +run-qemu-datasource-tests --TEST_SUITE=reset-test --FLAVOR=${{ matrix.flavor }}
upgrade-with-cli-test:
needs:
Expand Down Expand Up @@ -250,7 +273,7 @@ jobs:
export ISO=$PWD/$(ls *.iso)
sudo mkdir build
sudo mv $ISO build/
./earthly.sh +run-qemu-upgrade-test --FLAVOR=${{ matrix.flavor }} --CONTAINER_IMAGE=ttl.sh/kairos-${{ matrix.flavor }}-${{ github.sha }}:8h --TEST_SUITE=upgrade-with-cli
./earthly.sh +run-qemu-test --FLAVOR=${{ matrix.flavor }} --CONTAINER_IMAGE=ttl.sh/kairos-${{ matrix.flavor }}-${{ github.sha }}:8h --TEST_SUITE=upgrade-with-cli
- uses: actions/upload-artifact@v2
if: failure()
with:
Expand Down Expand Up @@ -313,7 +336,7 @@ jobs:
export ISO=$PWD/$(ls kairos-${{matrix.flavor}}-*.iso)
sudo mkdir build
sudo mv $ISO build/
./earthly.sh +run-qemu-upgrade-test --FLAVOR=${{ matrix.flavor }} --CONTAINER_IMAGE=ttl.sh/kairos-${{ matrix.flavor }}-${{ github.sha }}:8h --TEST_SUITE=upgrade-latest-with-cli
./earthly.sh +run-qemu-test --FLAVOR=${{ matrix.flavor }} --CONTAINER_IMAGE=ttl.sh/kairos-${{ matrix.flavor }}-${{ github.sha }}:8h --TEST_SUITE=upgrade-latest-with-cli
- uses: actions/upload-artifact@v2
if: failure()
with:
Expand Down
130 changes: 103 additions & 27 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ BUILD_GOLANG:
RUN go build -ldflags "-s -w" -o ${BIN} ./cmd/${SRC} && upx ${BIN}
SAVE ARTIFACT ${BIN} ${BIN} AS LOCAL build/${BIN}

uuidgen:
FROM alpine
RUN apk add uuidgen

COPY . ./

RUN echo $(uuidgen) > UUIDGEN

SAVE ARTIFACT UUIDGEN UUIDGEN

version:
FROM alpine
RUN apk add git
Expand Down Expand Up @@ -126,6 +136,10 @@ luet:
FROM quay.io/luet/base:$LUET_VERSION
SAVE ARTIFACT /usr/bin/luet /luet

###
### Image Build targets
###

framework:
ARG COSIGN_SKIP
ARG REPOSITORIES_FILE
Expand Down Expand Up @@ -254,6 +268,10 @@ docker-rootfs:
FROM +docker
SAVE ARTIFACT /. rootfs

###
### Artifacts targets (ISO, netboot, ARM)
###

iso:
ARG OSBUILDER_IMAGE
ARG ISO_NAME=${OS_ID}
Expand Down Expand Up @@ -327,8 +345,23 @@ ipxe-iso:
SAVE ARTIFACT /build/ipxe/src/bin/ipxe.iso iso AS LOCAL build/${ISO_NAME}-ipxe.iso.ipxe
SAVE ARTIFACT /build/ipxe/src/bin/ipxe.usb usb AS LOCAL build/${ISO_NAME}-ipxe-usb.img.ipxe

# Generic targets
# usage e.g. ./earthly.sh +datasource-iso --CLOUD_CONFIG=tests/assets/qrcode.yaml
datasource-iso:
ARG ELEMENTAL_IMAGE
ARG CLOUD_CONFIG
FROM $ELEMENTAL_IMAGE
RUN zypper in -y mkisofs
WORKDIR /build
RUN touch meta-data
COPY ${CLOUD_CONFIG} user-data
RUN cat user-data
RUN mkisofs -output ci.iso -volid cidata -joliet -rock user-data meta-data
SAVE ARTIFACT /build/ci.iso iso.iso AS LOCAL build/datasource.iso

## Security targets
###
### Security target scan
###
trivy:
FROM aquasec/trivy
SAVE ARTIFACT /usr/local/bin/trivy /trivy
Expand Down Expand Up @@ -356,62 +389,53 @@ linux-bench-scan:
COPY +linux-bench/linux-bench /build/linux-bench/linux-bench
RUN /build/linux-bench/linux-bench

# Generic targets
# usage e.g. ./earthly.sh +datasource-iso --CLOUD_CONFIG=tests/assets/qrcode.yaml
datasource-iso:
ARG ELEMENTAL_IMAGE
ARG CLOUD_CONFIG
FROM $ELEMENTAL_IMAGE
RUN zypper in -y mkisofs
WORKDIR /build
RUN touch meta-data
COPY ./${CLOUD_CONFIG} user-data
RUN cat user-data
RUN mkisofs -output ci.iso -volid cidata -joliet -rock user-data meta-data
SAVE ARTIFACT /build/ci.iso iso.iso AS LOCAL build/datasource.iso

# usage e.g. ./earthly.sh +run-qemu-tests --FLAVOR=alpine --FROM_ARTIFACTS=true
run-qemu-tests:
###
### Test targets
###
# usage e.g. ./earthly.sh +run-qemu-datasource-tests --FLAVOR=alpine --FROM_ARTIFACTS=true
run-qemu-datasource-tests:
FROM opensuse/leap
WORKDIR /test
RUN zypper in -y qemu-x86 qemu-arm qemu-tools go
ARG FLAVOR
ARG TEST_SUITE=autoinstall-test
ARG FROM_ARTIFACTS
ENV FLAVOR=$FLAVOR
ENV SSH_PORT=60022
ENV CREATE_VM=true
ARG CLOUD_CONFIG="/tests/tests/assets/autoinstall.yaml"
ARG CLOUD_CONFIG="./tests/assets/autoinstall.yaml"
ENV USE_QEMU=true

ENV GOPATH="/go"

RUN go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo
ENV CLOUD_CONFIG=$CLOUD_CONFIG

IF [ "$FROM_ARTIFACTS" = "true" ]
COPY . .
COPY . .
RUN ls -liah
IF [ -e /test/build/kairos.iso ]
ENV ISO=/test/build/kairos.iso
ENV DATASOURCE=/test/build/datasource.iso
ELSE
COPY ./tests .
COPY +iso/kairos.iso kairos.iso
COPY ( +datasource-iso/iso.iso --CLOUD_CONFIG=$CLOUD_CONFIG) datasource.iso
ENV ISO=/test/kairos.iso
END

IF [ ! -e /test/build/datasource.iso ]
COPY ( +datasource-iso/iso.iso --CLOUD_CONFIG=$CLOUD_CONFIG) datasource.iso
ENV DATASOURCE=/test/datasource.iso
ELSE
ENV DATASOURCE=/test/build/datasource.iso
END

ENV CLOUD_INIT=$CLOUD_CONFIG
ENV CLOUD_INIT=/tests/tests/$CLOUD_CONFIG

RUN PATH=$PATH:$GOPATH/bin ginkgo --label-filter "$TEST_SUITE" --fail-fast -r ./tests/

run-qemu-upgrade-test:
run-qemu-test:
FROM opensuse/leap
WORKDIR /test
RUN zypper in -y qemu-x86 qemu-arm qemu-tools go
ARG FLAVOR
ARG TEST_SUITE=upgrade-with-cli
ARG FROM_ARTIFACTS
ARG CONTAINER_IMAGE
ENV CONTAINER_IMAGE=$CONTAINER_IMAGE
ENV FLAVOR=$FLAVOR
Expand All @@ -428,3 +452,55 @@ run-qemu-upgrade-test:
ENV ISO=$ISO

RUN PATH=$PATH:$GOPATH/bin ginkgo --label-filter "$TEST_SUITE" --fail-fast -r ./tests/

# bundles tests needs to run in sequence:
# +prepare-bundles-tests
# +run-bundles-tests
prepare-bundles-tests:
ARG OSBUILDER_IMAGE
FROM $OSBUILDER_IMAGE
RUN zypper in -y jq docker
COPY +uuidgen/UUIDGEN ./
COPY +version/VERSION ./
ARG UUIDGEN=$(cat UUIDGEN)
ARG BUNDLE_IMAGE=ttl.sh/$UUIDGEN:8h
# BUILD +examples-bundle --BUNDLE_IMAGE=$BUNDLE_IMAGE
ARG VERSION=$(cat VERSION)
RUN echo "version ${VERSION}"
WITH DOCKER --load $IMG=(+examples-bundle --BUNDLE_IMAGE=$BUNDLE_IMAGE --VERSION=$VERSION)
RUN docker push $BUNDLE_IMAGE
END
BUILD +examples-bundle-config --BUNDLE_IMAGE=$BUNDLE_IMAGE

run-qemu-bundles-tests:
ARG FLAVOR
BUILD +run-qemu-datasource-tests --CLOUD_CONFIG=./bundles-config.yaml --TEST_SUITE="bundles-test" --FLAVOR=$FLAVOR

###
### Examples
###
### ./earthly.sh +examples-bundle --BUNDLE_IMAGE=ttl.sh/testfoobar:8h
examples-bundle:
ARG BUNDLE_IMAGE
ARG VERSION
FROM DOCKERFILE --build-arg VERSION=$VERSION -f examples/bundle/Dockerfile .
SAVE IMAGE $BUNDLE_IMAGE

## ./earthly.sh +examples-bundle-config --BUNDLE_IMAGE=ttl.sh/testfoobar:8h
## cat bundles-config.yaml
examples-bundle-config:
ARG BUNDLE_IMAGE
FROM alpine
COPY . .
RUN echo "" >> tests/assets/live-overlay.yaml
RUN echo "install:" >> tests/assets/live-overlay.yaml
RUN echo " auto: true" >> tests/assets/live-overlay.yaml
RUN echo " reboot: true" >> tests/assets/live-overlay.yaml
RUN echo " device: auto" >> tests/assets/live-overlay.yaml
RUN echo " grub_options:" >> tests/assets/live-overlay.yaml
RUN echo " extra_cmdline: foobarzz" >> tests/assets/live-overlay.yaml
RUN echo " bundles:" >> tests/assets/live-overlay.yaml
RUN echo " - rootfs_path: /usr/local/lib/extensions/kubo" >> tests/assets/live-overlay.yaml
RUN echo " targets:" >> tests/assets/live-overlay.yaml
RUN echo " - container://${BUNDLE_IMAGE}" >> tests/assets/live-overlay.yaml
SAVE ARTIFACT tests/assets/live-overlay.yaml AS LOCAL bundles-config.yaml
17 changes: 17 additions & 0 deletions examples/bundle/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM alpine as build
# Install a binary
ARG VERSION
ENV VERSION=$VERSION

RUN wget https://github.com/ipfs/kubo/releases/download/v0.15.0/kubo_v0.15.0_linux-amd64.tar.gz -O kubo.tar.gz
RUN tar xvf kubo.tar.gz
RUN mv kubo/ipfs /usr/bin/ipfs
RUN mkdir -p /usr/lib/extension-release.d/
RUN echo ID=kairos > /usr/lib/extension-release.d/extension-release.kubo
RUN echo VERSION_ID=$VERSION >> /usr/lib/extension-release.d/extension-release.kubo


FROM scratch

COPY --from=build /usr/bin/ipfs /usr/bin/ipfs
COPY --from=build /usr/lib/extension-release.d /usr/lib/extension-release.d
4 changes: 2 additions & 2 deletions internal/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ func Run(opts ...Option) error {
if !machine.SentinelExist("bundles") {
opts := c.Bundles.Options()
err := bundles.RunBundles(opts...)
if !c.IgnoreBundleErrors && err != nil {
if c.FailOnBundleErrors && err != nil {
return err
}

// Re-load providers
bus.Reload()
err = machine.CreateSentinel("bundles")
if !c.IgnoreBundleErrors && err != nil {
if c.FailOnBundleErrors && err != nil {
return err
}
}
Expand Down
30 changes: 30 additions & 0 deletions internal/agent/hooks/bundles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package hook

import (
config "github.com/kairos-io/kairos/pkg/config"
"github.com/kairos-io/kairos/pkg/machine"
"github.com/kairos-io/kairos/sdk/bundles"
)

type BundleOption struct{}

func (b BundleOption) Run(c config.Config) error {

machine.Mount("COS_PERSISTENT", "/usr/local") //nolint:errcheck
defer func() {
machine.Umount("/usr/local")
}()

machine.Mount("COS_OEM", "/oem") //nolint:errcheck
defer func() {
machine.Umount("/oem")
}()

opts := c.Install.Bundles.Options()
err := bundles.RunBundles(opts...)
if c.FailOnBundleErrors && err != nil {
return err
}

return nil
}
20 changes: 5 additions & 15 deletions internal/agent/hooks/gruboptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,20 @@ package hook

import (
"fmt"
"strings"

config "github.com/kairos-io/kairos/pkg/config"
"github.com/kairos-io/kairos/pkg/machine"
"github.com/kairos-io/kairos/pkg/utils"
)

type GrubOptions struct{}

func (b GrubOptions) Run(c config.Config) error {
oem, _ := utils.SH("blkid -L COS_OEM")
if oem == "" {
fmt.Println("OEM partition not found")
return nil // do not error out
}

oem = strings.TrimSuffix(oem, "\n")

oemMount, err := utils.SH(fmt.Sprintf("mkdir /tmp/oem && mount %s /tmp/oem", oem))
if err != nil {
fmt.Printf("could not mount oem: %s\n", oemMount+err.Error())
return nil // do not error out
}

machine.Mount("COS_OEM", "/tmp/oem") //nolint:errcheck
defer func() {
machine.Umount("/tmp/oem")
}()
for k, v := range c.Install.GrubOptions {
out, err := utils.SH(fmt.Sprintf("grub2-editenv /tmp/oem/grubenv set %s=%s", k, v))
if err != nil {
Expand All @@ -33,6 +24,5 @@ func (b GrubOptions) Run(c config.Config) error {
}
}

utils.SH("umount /tmp/oem") //nolint:errcheck
return nil
}
3 changes: 2 additions & 1 deletion internal/agent/hooks/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ type Interface interface {
var All = []Interface{
&RunStage{}, // Shells out to stages defined from the container image
&GrubOptions{}, // Set custom GRUB options
&Lifecycle{}, // Handles poweroff/reboot by config options
&BundleOption{},
&Lifecycle{}, // Handles poweroff/reboot by config options
}

func Run(c config.Config, hooks ...Interface) error {
Expand Down
3 changes: 2 additions & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Install struct {
Device string `yaml:"device,omitempty"`
Poweroff bool `yaml:"poweroff,omitempty"`
GrubOptions map[string]string `yaml:"grub_options,omitempty"`
Bundles Bundles `yaml:"bundles,omitempty"`
}

type Config struct {
Expand All @@ -33,7 +34,7 @@ type Config struct {
header string
ConfigURL string `yaml:"config_url,omitempty"`
Options map[string]string `yaml:"options,omitempty"`
IgnoreBundleErrors bool `yaml:"ignore_bundles_errors,omitempty"`
FailOnBundleErrors bool `yaml:"fail_on_bundles_errors,omitempty"`
Bundles Bundles `yaml:"bundles,omitempty"`
}

Expand Down
Loading

0 comments on commit e556d75

Please sign in to comment.