build rpi

This commit is contained in:
Lukasz Zajaczkowski
2025-01-10 14:32:09 +01:00
parent 4aa7211f96
commit 29922d33de
17 changed files with 7958 additions and 74 deletions

View File

@@ -1,26 +0,0 @@
name: Bump repositories
on:
schedule:
- cron: 0 20 * * *
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install earthly
uses: Luet-lab/luet-install-action@v1
with:
repository: quay.io/kairos/packages
packages: utils/earthly
- name: Bump cos 🔧
run: earthly +bump-repositories
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.PAT_TOKEN }}
push-to-fork: ci-forks/osbuilder
commit-message: ':arrow_up: Update repositories'
title: ':arrow_up: Update repositories'
body: Bump of Kairos repositories
signoff: true

View File

@@ -6,62 +6,55 @@ on:
branches:
- master
tags:
- '*'
concurrency:
group: image-${{ github.ref || github.head_ref }}
cancel-in-progress: true
- 'v*.*.*'
jobs:
docker:
runs-on: ubuntu-latest
publish-osbuilder:
name: Build and push osbuilder image
runs-on: ubuntu-22.04
permissions:
contents: 'read'
id-token: 'write'
packages: 'write'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=quay.io/kairos/osbuilder
VERSION=latest
SHORTREF=${GITHUB_SHA::8}
# If this is git tag, use the tag name as a docker tag
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
fi
TAGS="${DOCKER_IMAGE}:${VERSION},${DOCKER_IMAGE}:${SHORTREF}"
# If the VERSION looks like a version number, assume that
# this is the most recent version of the image and also
# tag it 'latest'.
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
TAGS="$TAGS,${DOCKER_IMAGE}:latest"
fi
# Set output parameters.
echo ::set-output name=tags::${TAGS}
echo ::set-output name=docker_image::${DOCKER_IMAGE}
- name: Set up QEMU
uses: docker/setup-qemu-action@master
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
platforms: all
images: |
ghcr.io/pluralsh/osbuilder
docker.io/pluralsh/osbuilder
tags: |
type=sha
type=match,pattern=bundle/v(.*),group=1
type=raw,value=latest,enable={{is_default_branch}}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@master
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: quay.io
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}
- name: Build
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker
uses: docker/login-action@v3
with:
username: mjgpluralsh
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
context: "."
file: "./Dockerfile"
push: true
tags: ${{ steps.prep.outputs.tags }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
GIT_COMMIT=${{ github.sha }}

View File

@@ -22,6 +22,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type Model string
const (
RPI3 Model = "rpi3"
RPI4 Model = "rpi4"
)
// OSArtifactSpec defines the desired state of OSArtifact
type OSArtifactSpec struct {
// There are 3 ways to specify a Kairos image:
@@ -37,6 +44,10 @@ type OSArtifactSpec struct {
ISO bool `json:"iso,omitempty"`
// +kubebuilder:validation:Type:=string
// +kubebuilder:validation:Enum:=rpi3;rpi4
Model *Model `json:"model,omitempty"`
//Disk-only stuff
DiskSize string `json:"diskSize,omitempty"`
CloudImage bool `json:"cloudImage,omitempty"`

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022.
@@ -94,6 +93,11 @@ func (in *OSArtifactSpec) DeepCopyInto(out *OSArtifactSpec) {
*out = new(SecretKeySelector)
**out = **in
}
if in.Model != nil {
in, out := &in.Model, &out.Model
*out = new(Model)
**out = **in
}
if in.CloudConfigRef != nil {
in, out := &in.CloudConfigRef, &out.CloudConfigRef
*out = new(SecretKeySelector)

View File

@@ -0,0 +1,10 @@
apiVersion: v2
appVersion: v0.1.0
description: A Helm chart for osbuilder
home: https://kairos.io/
maintainers:
- email: mudler@kairos.io
name: Ettore Di Giacinto
name: osbuilder
type: application
version: 0.1.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
To access the artifacts generated by your OSArtifact objects from the included nginx server add the following export to
your OSArtifact at `.spec.exporters[]`.
template:
spec:
restartPolicy: Never
containers:
- name: upload
image: {{ .Values.image.toolsRepository | default "quay.io/kairos/osbuilder-tools" }}:{{ .Values.image.tag | default .Chart.AppVersion }}
command:
- bash
args:
- -c
- |
for f in $(ls /artifacts)
do
curl -T /artifacts/$f http://osartifactbuilder-operator-osbuilder-nginx/upload/$f
done
volumeMounts:
- name: artifacts
mountPath: /artifacts

View File

@@ -0,0 +1,58 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "helm-chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "helm-chart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "helm-chart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "helm-chart.labels" -}}
helm.sh/chart: {{ include "helm-chart.chart" . }}
{{ include "helm-chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "helm-chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "helm-chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "helm-chart.serviceAccountName" -}}
{{- include "helm-chart.fullname" . }}
{{- end }}

View File

@@ -0,0 +1,54 @@
apiVersion: v1
data:
controller_manager_config.yaml: "apiVersion: controller-runtime.sigs.k8s.io/v1alpha1\nkind:
ControllerManagerConfig\nhealth:\n healthProbeBindAddress: :8081\nmetrics:\n
\ bindAddress: 127.0.0.1:8080\nwebhook:\n port: 9443\nleaderElection:\n leaderElect:
true\n resourceName: 98ca89ca.kairos.io\n# leaderElectionReleaseOnCancel
defines if the leader should step down volume \n# when the Manager ends.
This requires the binary to immediately end when the\n# Manager is stopped,
otherwise, this setting is unsafe. Setting this significantly\n# speeds
up voluntary leader transitions as the new leader don't have to wait\n# LeaseDuration
time first.\n# In the default scaffold provided, the program ends immediately
after \n# the manager stops, so would be fine to enable this option. However,
\n# if you are doing or is intended to do any operation such as perform
cleanups \n# after the manager stops then its usage might be unsafe.\n#
\ leaderElectionReleaseOnCancel: true\n"
kind: ConfigMap
metadata:
name: osartifactbuilder-operator-manager-config
namespace: '{{.Release.Namespace}}'
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
server {
listen 80;
server_name localhost;
client_max_body_size 11000M;
#access_log /var/log/nginx/host.access.log main;
location ~ "/upload/([0-9a-zA-Z-.]*)$" {
alias /usr/share/nginx/html/$1;
client_body_temp_path /tmp;
dav_methods PUT DELETE MKCOL COPY MOVE;
create_full_put_path on;
dav_access group:rw all:r;
}
location / {
root /usr/share/nginx/html;
autoindex on;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@@ -0,0 +1,132 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: '{{ include "helm-chart.fullname" . }}'
namespace: '{{.Release.Namespace}}'
labels:
{{- include "helm-chart.labels" . | nindent 8 }}
spec:
replicas: 1
selector:
matchLabels:
{{- include "helm-chart.selectorLabels" . | nindent 10 }}
template:
metadata:
annotations:
{{- range keys .Values.podAnnotations }}
{{ . | quote }}: {{ get $.Values.podAnnotations . | quote}}
{{- end }}
labels:
{{- include "helm-chart.selectorLabels" . | nindent 14}}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 14 }}
{{- end }}
containers:
- args:
- --secure-listen-address=0.0.0.0:8443
- --upstream=http://127.0.0.1:8080/
- --logtostderr=true
- --v=0
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.11.0
name: kube-rbac-proxy
ports:
- containerPort: 8443
name: https
protocol: TCP
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 5m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
- args:
- --health-probe-bind-address=:8081
- --metrics-bind-address=127.0.0.1:8080
- --leader-elect
- '--tool-image={{ .Values.toolsImage.repository | default "quay.io/kairos/auroraboot" }}:{{ .Values.toolsImage.tag | default "latest" }}'
command:
- /manager
image: '{{ .Values.image.repository | default "quay.io/kairos/osbuilder" }}:{{ .Values.image.tag | default .Chart.AppVersion }}'
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
name: manager
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
{{- if and .Values.resources .Values.resources.controller }}
resources:
{{ toYaml .Values.resources.controller | indent 20 }}
{{- end }}
securityContext:
allowPrivilegeEscalation: false
securityContext:
runAsNonRoot: true
serviceAccountName: '{{ include "helm-chart.serviceAccountName" . }}'
terminationGracePeriodSeconds: 10
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 14 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 14 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 14 }}
{{- end }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: osbuilder-nginx
name: 'osbuilder-nginx'
namespace: '{{.Release.Namespace}}'
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: osbuilder-nginx
template:
metadata:
labels:
app.kubernetes.io/name: osbuilder-nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-public
- mountPath: /etc/nginx/conf.d
name: config
readOnly: true
serviceAccountName: '{{ include "helm-chart.serviceAccountName" . }}'
terminationGracePeriodSeconds: 10
securityContext:
fsGroup: 101
volumes:
- name: nginx-public
persistentVolumeClaim:
claimName: osartifactbuilder-operator-nginx-public
- name: config
configMap:
name: nginx-config
items:
- key: nginx.conf
path: default.conf

View File

@@ -0,0 +1,12 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: osartifactbuilder-operator-nginx-public
namespace: '{{.Release.Namespace}}'
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: '{{ .Values.nginx.pvcSize }}'

View File

@@ -0,0 +1,180 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: osartifactbuilder-operator-leader-election-role
namespace: '{{.Release.Namespace}}'
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: osartifactbuilder-operator-manager-role
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- get
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- apiGroups:
- batch
resources:
- jobs
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- build.kairos.io
resources:
- osartifacts
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- build.kairos.io
resources:
- osartifacts/finalizers
verbs:
- update
- apiGroups:
- build.kairos.io
resources:
- osartifacts/status
verbs:
- get
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: osartifactbuilder-operator-metrics-reader
rules:
- nonResourceURLs:
- /metrics
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: osartifactbuilder-operator-proxy-role
rules:
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: osartifactbuilder-operator-leader-election-rolebinding
namespace: '{{.Release.Namespace}}'
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: osartifactbuilder-operator-leader-election-role
subjects:
- kind: ServiceAccount
name: '{{ include "helm-chart.serviceAccountName" . }}'
namespace: '{{.Release.Namespace}}'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: osartifactbuilder-operator-manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: osartifactbuilder-operator-manager-role
subjects:
- kind: ServiceAccount
name: '{{ include "helm-chart.serviceAccountName" . }}'
namespace: '{{.Release.Namespace}}'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: osartifactbuilder-operator-proxy-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: osartifactbuilder-operator-proxy-role
subjects:
- kind: ServiceAccount
name: '{{ include "helm-chart.serviceAccountName" . }}'
namespace: '{{.Release.Namespace}}'

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
name: '{{ include "helm-chart.fullname" . }}-metrics-service'
namespace: '{{.Release.Namespace}}'
spec:
ports:
- name: https
port: 8443
protocol: TCP
targetPort: https
selector:
{{- include "helm-chart.selectorLabels" . | nindent 6 }}
---
apiVersion: v1
kind: Service
metadata:
name: osartifactbuilder-operator-osbuilder-nginx
namespace: '{{.Release.Namespace}}'
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app.kubernetes.io/name: osbuilder-nginx
type: NodePort

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: '{{ include "helm-chart.serviceAccountName" . }}'
namespace: '{{.Release.Namespace}}'

View File

@@ -0,0 +1,51 @@
# Settings for the chart.
# nameOverride Replaces the release name of the chart in Chart.yaml file when
# this is used to construct Kubernetes object names
nameOverride: ""
# fullnameOverride completely replaces the generated release name
fullnameOverride: ""
# Secrets to pull container images from private registries
imagePullSecrets: []
image:
# controller image to be used. Leave empty to use
repository: ""
# tag of the controller image. Leave empty to use chart's AppVersion
tag: ""
toolsImage:
repository: "quay.io/kairos/auroraboot"
tag: "latest"
podAnnotations: {}
nodeSelector: {}
tolerations: []
affinity: {}
tls:
# source options:
# - "cert-manager-self-signed": Scaffold cert-manager integration, and create
# a self-signed certificate with a cert-manager self-signed Issuer. Depends
# on cert-manager. (default)
# - "cert-manager": Scafffold cert-manager integration. User configures their
# own Issuer. Depends on cert-manager. Set tls.certManagerIssuerName to the
# desired Issuer.
source: cert-manager-self-signed
# "cert-manager"-only options:
certManagerIssuerName: ""
nginx:
pvcSize: 30Gi
## Resource limits & requests
## Ref: https://kubernetes.io/docs/user-guide/compute-resources/
resources:
controller:
limits:
cpu: 500m
memory: 50Mi
requests:
cpu: 250m
memory: 50Mi

View File

@@ -7141,6 +7141,11 @@ spec:
type: boolean
kairosRelease:
type: string
model:
enum:
- rpi3
- rpi4
type: string
netboot:
type: boolean
netbootURL:

View File

@@ -201,6 +201,9 @@ func (r *OSArtifactReconciler) newBuilderPod(pvcName string, artifact *osbuilder
artifact.Name,
)
}
if artifact.Spec.Model != nil {
cmd = fmt.Sprintf("/build-arm-image.sh --model %s --state-partition-size 6200 --recovery-partition-size 4200 --size 15200 --images-size 2000 --config /iso/iso-overlay/cloud_config.yaml --docker-image %s /artifacts/%s.iso", *artifact.Spec.Model, artifact.Spec.ImageName, artifact.Name)
}
buildIsoContainer := corev1.Container{
ImagePullPolicy: corev1.PullAlways,
@@ -407,6 +410,12 @@ func (r *OSArtifactReconciler) newBuilderPod(pvcName string, artifact *osbuilder
podSpec.Containers = append(podSpec.Containers, createImageContainer(r.ToolImage, artifact))
if artifact.Spec.ISO && artifact.Spec.Model != nil {
podSpec.InitContainers = []corev1.Container{}
podSpec.Containers = make([]corev1.Container, 0)
podSpec.Containers = append(podSpec.Containers, buildIsoContainer)
}
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
GenerateName: artifact.Name + "-",