mirror of
https://github.com/kairos-io/osbuilder.git
synced 2025-12-25 04:42:52 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52d4f1d60b | ||
|
|
a923f2e558 | ||
|
|
e7bafb6ae5 | ||
|
|
6b69df91a5 | ||
|
|
b70b22bb35 | ||
|
|
b8e1a4ff2e | ||
|
|
4ce89a76a9 | ||
|
|
5b3c765080 | ||
|
|
893de1cc1d | ||
|
|
3eafb953b2 | ||
|
|
278abfa84d | ||
|
|
d8d8d70eca | ||
|
|
f59f5bac75 | ||
|
|
1372a93911 | ||
|
|
ccc0d52393 | ||
|
|
b65986b47e |
@@ -38,7 +38,3 @@ spec:
|
||||
- "--health-probe-bind-address=:8081"
|
||||
- "--metrics-bind-address=127.0.0.1:8080"
|
||||
- "--leader-elect"
|
||||
- "--copy-to-namespace=$(NGINX_NAMESPACE)"
|
||||
- "--copy-role=$(ARTIFACT_COPIER_ROLE)"
|
||||
- --copy-to-pod-label=app.kubernetes.io/name=osbuilder-nginx
|
||||
- --copy-to-path="/usr/share/nginx/html"
|
||||
|
||||
@@ -2,5 +2,11 @@
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
],
|
||||
"schedule": [
|
||||
"after 11pm every weekday",
|
||||
"before 7am every weekday",
|
||||
"every weekend"
|
||||
],
|
||||
"timezone": "Europe/Brussels"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package e2e_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
osbuilder "github.com/kairos-io/osbuilder/api/v1alpha2"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
@@ -16,48 +18,54 @@ import (
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/dynamic"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ = Describe("ISO build test", func() {
|
||||
k8s := dynamic.NewForConfigOrDie(ctrl.GetConfigOrDie())
|
||||
scheme := runtime.NewScheme()
|
||||
_ = osbuilder.AddToScheme(scheme)
|
||||
|
||||
var artifactName string
|
||||
artifacts := k8s.Resource(schema.GroupVersionResource{Group: osbuilder.GroupVersion.Group, Version: osbuilder.GroupVersion.Version, Resource: "osartifacts"}).Namespace("default")
|
||||
pods := k8s.Resource(schema.GroupVersionResource{Group: corev1.GroupName, Version: corev1.SchemeGroupVersion.Version, Resource: "pods"}).Namespace("default")
|
||||
pvcs := k8s.Resource(schema.GroupVersionResource{Group: corev1.GroupName, Version: corev1.SchemeGroupVersion.Version, Resource: "persistentvolumeclaims"}).Namespace("default")
|
||||
jobs := k8s.Resource(schema.GroupVersionResource{Group: batchv1.GroupName, Version: batchv1.SchemeGroupVersion.Version, Resource: "jobs"}).Namespace("default")
|
||||
var artifacts, pods, pvcs, jobs dynamic.ResourceInterface
|
||||
var scheme *runtime.Scheme
|
||||
var artifactLabelSelector labels.Selector
|
||||
|
||||
artifact := &osbuilder.OSArtifact{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "OSArtifact",
|
||||
APIVersion: osbuilder.GroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "simple-",
|
||||
},
|
||||
Spec: osbuilder.OSArtifactSpec{
|
||||
ImageName: "quay.io/kairos/core-opensuse:latest",
|
||||
ISO: true,
|
||||
DiskSize: "",
|
||||
Exporters: []batchv1.JobSpec{
|
||||
{
|
||||
Template: corev1.PodTemplateSpec{
|
||||
Spec: corev1.PodSpec{
|
||||
RestartPolicy: corev1.RestartPolicyNever,
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "test",
|
||||
Image: "debian:latest",
|
||||
Command: []string{"bash"},
|
||||
Args: []string{"-xec", "[ -f /artifacts/*.iso ]"},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "artifacts",
|
||||
ReadOnly: true,
|
||||
MountPath: "/artifacts",
|
||||
BeforeEach(func() {
|
||||
k8s := dynamic.NewForConfigOrDie(ctrl.GetConfigOrDie())
|
||||
scheme = runtime.NewScheme()
|
||||
err := osbuilder.AddToScheme(scheme)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
artifacts = k8s.Resource(schema.GroupVersionResource{Group: osbuilder.GroupVersion.Group, Version: osbuilder.GroupVersion.Version, Resource: "osartifacts"}).Namespace("default")
|
||||
pods = k8s.Resource(schema.GroupVersionResource{Group: corev1.GroupName, Version: corev1.SchemeGroupVersion.Version, Resource: "pods"}).Namespace("default")
|
||||
pvcs = k8s.Resource(schema.GroupVersionResource{Group: corev1.GroupName, Version: corev1.SchemeGroupVersion.Version, Resource: "persistentvolumeclaims"}).Namespace("default")
|
||||
jobs = k8s.Resource(schema.GroupVersionResource{Group: batchv1.GroupName, Version: batchv1.SchemeGroupVersion.Version, Resource: "jobs"}).Namespace("default")
|
||||
|
||||
artifact := &osbuilder.OSArtifact{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "OSArtifact",
|
||||
APIVersion: osbuilder.GroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "simple-",
|
||||
},
|
||||
Spec: osbuilder.OSArtifactSpec{
|
||||
ImageName: "quay.io/kairos/core-opensuse:latest",
|
||||
ISO: true,
|
||||
DiskSize: "",
|
||||
Exporters: []batchv1.JobSpec{
|
||||
{
|
||||
Template: corev1.PodTemplateSpec{
|
||||
Spec: corev1.PodSpec{
|
||||
RestartPolicy: corev1.RestartPolicyNever,
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "test",
|
||||
Image: "debian:latest",
|
||||
Command: []string{"bash"},
|
||||
Args: []string{"-xec", "[ -f /artifacts/*.iso ]"},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "artifacts",
|
||||
ReadOnly: true,
|
||||
MountPath: "/artifacts",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -66,92 +74,89 @@ var _ = Describe("ISO build test", func() {
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
uArtifact := unstructured.Unstructured{}
|
||||
uArtifact.Object, _ = runtime.DefaultUnstructuredConverter.ToUnstructured(artifact)
|
||||
resp, err := artifacts.Create(context.TODO(), &uArtifact, metav1.CreateOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
artifactName = resp.GetName()
|
||||
uArtifact := unstructured.Unstructured{}
|
||||
uArtifact.Object, _ = runtime.DefaultUnstructuredConverter.ToUnstructured(artifact)
|
||||
resp, err := artifacts.Create(context.TODO(), &uArtifact, metav1.CreateOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
artifactName = resp.GetName()
|
||||
|
||||
Context("simple", func() {
|
||||
artifactLabelSelectorReq, _ := labels.NewRequirement("build.kairos.io/artifact", selection.Equals, []string{artifactName})
|
||||
artifactLabelSelector := labels.NewSelector().Add(*artifactLabelSelectorReq)
|
||||
artifactLabelSelectorReq, err := labels.NewRequirement("build.kairos.io/artifact", selection.Equals, []string{artifactName})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
artifactLabelSelector = labels.NewSelector().Add(*artifactLabelSelectorReq)
|
||||
})
|
||||
|
||||
It("starts the build", func() {
|
||||
Eventually(func(g Gomega) {
|
||||
w, err := pods.Watch(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
var stopped bool
|
||||
for !stopped {
|
||||
event, ok := <-w.ResultChan()
|
||||
|
||||
stopped = event.Type != watch.Deleted && event.Type != watch.Error || !ok
|
||||
}
|
||||
}).WithTimeout(time.Hour).Should(Succeed())
|
||||
})
|
||||
|
||||
It("exports the artifacts", func() {
|
||||
Eventually(func(g Gomega) {
|
||||
w, err := jobs.Watch(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
var stopped bool
|
||||
for !stopped {
|
||||
event, ok := <-w.ResultChan()
|
||||
|
||||
stopped = event.Type != watch.Deleted && event.Type != watch.Error || !ok
|
||||
}
|
||||
}).WithTimeout(time.Hour).Should(Succeed())
|
||||
})
|
||||
|
||||
It("artifact successfully builds", func() {
|
||||
Eventually(func(g Gomega) {
|
||||
w, err := artifacts.Watch(context.TODO(), metav1.ListOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
var artifact osbuilder.OSArtifact
|
||||
var stopped bool
|
||||
for !stopped {
|
||||
event, ok := <-w.ResultChan()
|
||||
stopped = !ok
|
||||
|
||||
if event.Type == watch.Modified && event.Object.(*unstructured.Unstructured).GetName() == artifactName {
|
||||
err := scheme.Convert(event.Object, &artifact, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
stopped = artifact.Status.Phase == osbuilder.Ready
|
||||
}
|
||||
|
||||
}
|
||||
}).WithTimeout(time.Hour).Should(Succeed())
|
||||
})
|
||||
|
||||
It("cleans up resources on deleted", func() {
|
||||
err := artifacts.Delete(context.TODO(), artifactName, metav1.DeleteOptions{})
|
||||
It("works", func() {
|
||||
By("starting the build")
|
||||
Eventually(func(g Gomega) {
|
||||
w, err := pods.Watch(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := artifacts.List(context.TODO(), metav1.ListOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := pods.List(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := pvcs.List(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := jobs.List(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
})
|
||||
var stopped bool
|
||||
for !stopped {
|
||||
event, ok := <-w.ResultChan()
|
||||
|
||||
stopped = event.Type != watch.Deleted && event.Type != watch.Error || !ok
|
||||
}
|
||||
}).WithTimeout(time.Hour).Should(Succeed())
|
||||
|
||||
By("exporting the artifacts")
|
||||
Eventually(func(g Gomega) {
|
||||
w, err := jobs.Watch(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
var stopped bool
|
||||
for !stopped {
|
||||
event, ok := <-w.ResultChan()
|
||||
|
||||
stopped = event.Type != watch.Deleted && event.Type != watch.Error || !ok
|
||||
}
|
||||
}).WithTimeout(time.Hour).Should(Succeed())
|
||||
|
||||
By("building the artifacts successfully")
|
||||
Eventually(func(g Gomega) {
|
||||
w, err := artifacts.Watch(context.TODO(), metav1.ListOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
var artifact osbuilder.OSArtifact
|
||||
var stopped bool
|
||||
for !stopped {
|
||||
event, ok := <-w.ResultChan()
|
||||
stopped = !ok
|
||||
|
||||
if event.Type == watch.Modified && event.Object.(*unstructured.Unstructured).GetName() == artifactName {
|
||||
err := scheme.Convert(event.Object, &artifact, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
stopped = artifact.Status.Phase == osbuilder.Ready
|
||||
}
|
||||
|
||||
}
|
||||
}).WithTimeout(time.Hour).Should(Succeed())
|
||||
|
||||
By("cleaning up resources on deletion")
|
||||
err := artifacts.Delete(context.TODO(), artifactName, metav1.DeleteOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := artifacts.List(context.TODO(), metav1.ListOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := pods.List(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := pvcs.List(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
Eventually(func(g Gomega) int {
|
||||
res, err := jobs.List(context.TODO(), metav1.ListOptions{LabelSelector: artifactLabelSelector.String()})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return len(res.Items)
|
||||
}).WithTimeout(time.Minute).Should(Equal(0))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -71,7 +71,7 @@ COPY --from=grub-artifacts / /arm/grub/artifacts
|
||||
RUN zypper ref && zypper dup -y
|
||||
|
||||
## ISO Build depedencies
|
||||
RUN zypper ref && zypper in -y xfsprogs parted util-linux-systemd e2fsprogs curl util-linux udev rsync grub2 dosfstools grub2-x86_64-efi squashfs mtools xorriso lvm2
|
||||
RUN zypper ref && zypper in -y xfsprogs parted util-linux-systemd e2fsprogs curl util-linux udev rsync grub2 dosfstools grub2-x86_64-efi squashfs mtools xorriso lvm2 zstd
|
||||
RUN mkdir /config
|
||||
|
||||
# Arm image build deps
|
||||
@@ -85,6 +85,8 @@ RUN zypper in -y bc qemu-tools
|
||||
COPY ./config.yaml /config/manifest.yaml
|
||||
COPY ./entrypoint.sh /entrypoint.sh
|
||||
COPY ./add-cloud-init.sh /add-cloud-init.sh
|
||||
COPY ./os-release.tmpl /os-release.tmpl
|
||||
COPY ./update-os-release.sh /update-os-release.sh
|
||||
|
||||
# ARM helpers
|
||||
COPY ./build-arm-image.sh /build-arm-image.sh
|
||||
|
||||
@@ -72,14 +72,7 @@ cleanup() {
|
||||
umount $oem || true
|
||||
fi
|
||||
|
||||
if [ "$disable_lvm" == "false" ]; then
|
||||
lvremove --yes KairosVG
|
||||
fi
|
||||
MAPPER_LOOP=$(basename "$LOOP")
|
||||
for LOOPPART in $(ls /dev/mapper/"${MAPPER_LOOP}"*| awk -F'/' {'print $4'}); do
|
||||
dmsetup remove "${LOOPPART}" || true;
|
||||
done;
|
||||
losetup -d "${LOOP}" || true;
|
||||
losetup -D "${LOOP}" || true;
|
||||
}
|
||||
|
||||
ensure_dir_structure() {
|
||||
@@ -352,6 +345,8 @@ partprobe
|
||||
|
||||
echo ">> Writing image and partition table"
|
||||
dd if=/dev/zero of="${output_image}" bs=1024000 count="${size}" || exit 1
|
||||
# make it gpt
|
||||
echo "label: gpt" | sfdisk "${output_image}"
|
||||
if [ "$model" == "rpi64" ]; then
|
||||
sgdisk -n 1:8192:+96M -c 1:EFI -t 1:0c00 ${output_image}
|
||||
else
|
||||
@@ -365,7 +360,8 @@ sgdisk -n 3:0:+$(( ${recovery_size} + ${oem_size} ))M -c 3:lvm -t 3:8e00 ${outpu
|
||||
fi
|
||||
sgdisk -n 4:0:+64M -c 4:persistent -t 4:8300 ${output_image}
|
||||
|
||||
sgdisk -m 1:2:3:4 ${output_image}
|
||||
# Make the disk GPT
|
||||
sgdisk -g ${output_image}
|
||||
|
||||
if [ "$model" == "rpi64" ]; then
|
||||
sfdisk --part-type ${output_image} 1 c
|
||||
@@ -390,7 +386,7 @@ export device="/dev/mapper/${device}"
|
||||
|
||||
partprobe
|
||||
|
||||
kpartx -va $DRIVE
|
||||
kpartx -vag $DRIVE
|
||||
|
||||
echo ">> Populating partitions"
|
||||
efi=${device}p1
|
||||
@@ -478,7 +474,7 @@ sync
|
||||
sleep 5
|
||||
sync
|
||||
|
||||
kpartx -dv $DRIVE || true
|
||||
kpartx -dvg $DRIVE || true
|
||||
|
||||
umount $DRIVE || true
|
||||
|
||||
|
||||
13
tools-image/os-release.tmpl
Normal file
13
tools-image/os-release.tmpl
Normal file
@@ -0,0 +1,13 @@
|
||||
KAIROS_NAME="${OS_NAME}"
|
||||
KAIROS_VERSION="${OS_VERSION}"
|
||||
KAIROS_ID="${OS_ID}"
|
||||
KAIROS_ID_LIKE="${OS_NAME}"
|
||||
KAIROS_VERSION_ID="${OS_VERSION}"
|
||||
KAIROS_PRETTY_NAME="${OS_NAME} ${OS_VERSION}"
|
||||
KAIROS_BUG_REPORT_URL="${BUG_REPORT_URL}"
|
||||
KAIROS_HOME_URL="${HOME_URL}"
|
||||
KAIROS_IMAGE_REPO="${OS_REPO}"
|
||||
KAIROS_IMAGE_LABEL="${OS_LABEL}"
|
||||
KAIROS_GITHUB_REPO="${GITHUB_REPO}"
|
||||
KAIROS_VARIANT="${VARIANT}"
|
||||
KAIROS_FLAVOR="${FLAVOR}"
|
||||
23
tools-image/update-os-release.sh
Executable file
23
tools-image/update-os-release.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# usage:
|
||||
# docker run --rm -ti --entrypoint /update-os-release.sh \
|
||||
# -v /etc:/workspace \ # mount the directory where your os-release is, this is by default in /etc but you can mount a different dir for testing
|
||||
# -e OS_NAME=kairos-core-opensuse-leap \
|
||||
# -e OS_VERSION=v2.2.0 \
|
||||
# -e OS_ID="kairos" \
|
||||
# -e OS_NAME=kairos-core-opensuse-leap \
|
||||
# -e BUG_REPORT_URL="https://github.com/kairos-io/kairos/issues" \
|
||||
# -e HOME_URL="https://github.com/kairos-io/kairos" \
|
||||
# -e OS_REPO="quay.io/kairos/core-opensuse-leap" \
|
||||
# -e OS_LABEL="latest" \
|
||||
# -e GITHUB_REPO="kairos-io/kairos" \
|
||||
# -e VARIANT="core" \
|
||||
# -e FLAVOR="opensuse-leap"
|
||||
# quay.io/kairos/osbuilder-tools:latest
|
||||
|
||||
set -ex
|
||||
|
||||
sed -i -n '/KAIROS_/!p' /workspace/os-release
|
||||
envsubst >>/workspace/os-release < /os-release.tmpl
|
||||
|
||||
cat /workspace/os-release
|
||||
Reference in New Issue
Block a user