Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copy to .env and fill in real values.
# .env is gitignored; this file is safe to commit.

# Unikraft Cloud credentials for the k8s-operator.
# When set, task test:setup injects these into the test cluster.
# When unset, the operator runs with dummy credentials (hermetic mode).
UKC_METRO=
UKC_TOKEN=
40 changes: 40 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: build

on:
push:
release:
types: ["published"]

jobs:
validate-kustomize:
uses: datum-cloud/actions/.github/workflows/validate-kustomize.yaml@v1.13.2

publish-container-image:
needs:
- validate-kustomize
permissions:
id-token: write
contents: read
packages: write
attestations: write
uses: datum-cloud/actions/.github/workflows/publish-docker.yaml@v1.13.2
with:
image-name: unikraft-provider
platforms: linux/amd64,linux/arm64
secrets: inherit

publish-kustomize-bundle:
needs:
- validate-kustomize
- publish-container-image
permissions:
id-token: write
contents: read
packages: write
uses: datum-cloud/actions/.github/workflows/publish-kustomize-bundle.yaml@v1.13.2
with:
bundle-name: ghcr.io/datum-cloud/unikraft-provider-kustomize
bundle-path: config
image-overlays: config/default
image-name: ghcr.io/datum-cloud/unikraft-provider
secrets: inherit
26 changes: 26 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: e2e
on:
pull_request:
push:
branches: [main]

jobs:
e2e:
runs-on: ubuntu-latest
env:
TASK_X_REMOTE_TASKFILES: '1'
steps:
- uses: actions/checkout@v6
- uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: datum-cloud/test-infra/.github/actions/kind-bootstrap@v0.6.4
with:
cluster-name: test-infra
- run: task test:install-dependencies
- run: task dev:build
- run: task dev:load
- run: task test:deploy
- uses: kyverno/action-install-chainsaw@v0.2.12
- run: task e2e
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bin/
.test-infra/
.task/
.env
7 changes: 3 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.22 AS builder
FROM golang:1.25 AS builder
ARG TARGETOS
ARG TARGETARCH

Expand All @@ -12,9 +12,8 @@ COPY go.sum go.sum
RUN go mod download

# Copy the go source
COPY cmd/main.go cmd/main.go
COPY api/ api/
COPY internal/controller/ internal/controller/
COPY cmd/ cmd/
COPY internal/ internal/

# Build
# the GOARCH has not a default value to allow the binary be built according to the host where the command
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,27 @@ The operator will process the Instance and create corresponding resources in the
```bash
kubectl get instances.compute.datumapis.com
```

## Testing

End-to-end tests run against a hermetic kind cluster provisioned by
[`datum-cloud/test-infra`](https://github.com/datum-cloud/test-infra) and
driven by [Task](https://taskfile.dev) + [Chainsaw](https://kyverno.github.io/chainsaw/).

### Prerequisites

- `docker`, `kind`
- `task` (>= 3.x), with `TASK_X_REMOTE_TASKFILES=1` exported
- `chainsaw`
- Downstream CRDs for `github.com/unikraft-cloud/k8s-operator` dropped into
`config/dependencies/unikraft-k8s-operator-crds/` (the upstream repo is
private so the CRDs cannot be fetched automatically)

### Local flow

```bash
export TASK_X_REMOTE_TASKFILES=1
task test:setup # kind up, install CRDs, build + load image, deploy provider
task e2e # run chainsaw tests
task test:teardown # delete kind cluster
```
87 changes: 87 additions & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
version: '3'

dotenv: ['.env']

vars:
TEST_INFRA_REPO_REF: 'v0.6.4'
TEST_INFRA_CLUSTER_NAME: 'test-infra'
IMG_NAME: 'ghcr.io/datum-cloud/unikraft-provider'
IMG_TAG: 'dev'
IMG: '{{.IMG_NAME}}:{{.IMG_TAG}}'

includes:
test-infra:
taskfile: https://raw.githubusercontent.com/datum-cloud/test-infra/{{.TEST_INFRA_REPO_REF}}/Taskfile.yml
checksum: fe14263f3d0c3f246f1d8bc7fb90b3d82f0069792e1a46cdb49e761624051223
vars:
REPO_REF: '{{.TEST_INFRA_REPO_REF}}'

tasks:
default:
cmds:
- task --list
silent: true

dev:build:
desc: Build the unikraft-provider container image
silent: true
cmds:
- docker build -t {{.IMG}} .

dev:load:
desc: Load the image into the kind cluster
silent: true
cmds:
- kind load docker-image {{.IMG}} --name {{.TEST_INFRA_CLUSTER_NAME}}

test:create-ukc-credentials:
desc: Create UKC credentials Secret from UKC_METRO / UKC_TOKEN env vars
silent: true
status:
- test -z "${UKC_METRO}" -a -z "${UKC_TOKEN}"
cmds:
- task test-infra:kubectl -- create namespace ukc-operator --dry-run=client -o yaml | task test-infra:kubectl -- apply -f -
- |
task test-infra:kubectl -- create secret generic ukc-credentials \
--namespace ukc-operator \
--from-literal=values.yaml="$(printf 'ukc:\n metro: %s\n token: %s\n' "${UKC_METRO}" "${UKC_TOKEN}")" \
--dry-run=client -o yaml | task test-infra:kubectl -- apply -f -

test:install-dependencies:
desc: Install compute and unikraft k8s-operator via Flux
silent: true
cmds:
- task: test:create-ukc-credentials
- task test-infra:kubectl -- apply -k config/dependencies/compute
- task test-infra:kubectl -- apply -k config/dependencies/unikraft-k8s-operator
- task test-infra:kubectl -- wait -n flux-system kustomization/compute --for=condition=Ready --timeout=300s
- task test-infra:kubectl -- wait -n ukc-operator helmrelease/unikraft-k8s-operator --for=condition=Ready --timeout=180s

test:deploy:
desc: Deploy the unikraft-provider via the test-infra overlay
silent: true
cmds:
- task test-infra:kubectl -- apply -k config/overlays/test-infra
- task test-infra:kubectl -- rollout status -n infra-provider-unikraft-system deployment/infra-provider-unikraft-controller-manager --timeout=180s

test:setup:
desc: Bring up kind, install deps, build/load image, deploy
silent: true
deps: [test-infra:cluster-up]
cmds:
- task: test:install-dependencies
- task: dev:build
- task: dev:load
- task: test:deploy

e2e:
desc: Run chainsaw e2e tests
silent: true
cmds:
- chainsaw test test/e2e --config test/e2e/.chainsaw.yaml

test:teardown:
desc: Tear down the kind cluster
silent: true
cmds:
- task: test-infra:cluster-down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
"go.datum.net/unikraft-provider/internal/config"
"go.datum.net/unikraft-provider/internal/controller"
networkingv1alpha "go.datum.net/network-services-operator/api/v1alpha"
computev1alpha "go.datum.net/workload-operator/api/v1alpha"
computev1alpha "go.datum.net/compute/api/v1alpha"
mcproviders "go.miloapis.com/milo/pkg/multicluster-runtime"
mcmilo "go.miloapis.com/milo/pkg/multicluster-runtime/milo"
// +kubebuilder:scaffold:imports
Expand Down
7 changes: 1 addition & 6 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ resources:
- metrics_service.yaml

# Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager
patches:
# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.
# More info: https://book.kubebuilder.io/reference/metrics
- path: manager_metrics_patch.yaml
target:
kind: Deployment
#patches:

# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
Expand Down
14 changes: 14 additions & 0 deletions config/dependencies/compute/flux-install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: compute
spec:
interval: 10m
retryInterval: 1m
timeout: 3m
prune: true
wait: true
sourceRef:
kind: OCIRepository
name: compute
path: overlays/single-cluster
6 changes: 6 additions & 0 deletions config/dependencies/compute/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: flux-system
resources:
- ocirepository.yaml
- flux-install.yaml
9 changes: 9 additions & 0 deletions config/dependencies/compute/ocirepository.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: compute
spec:
interval: 1h
url: oci://ghcr.io/datum-cloud/compute-kustomize
ref:
tag: v0.6.0
28 changes: 28 additions & 0 deletions config/dependencies/unikraft-k8s-operator/helmrelease.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: unikraft-k8s-operator
spec:
interval: 1h
chart:
spec:
chart: k8s-operator
version: 0.1.0
sourceRef:
kind: HelmRepository
name: unikraft-cloud
install:
crds: Create
upgrade:
crds: CreateReplace
valuesFrom:
# Real credentials injected via task test:create-ukc-credentials.
# When the Secret exists, its values override the fallback ConfigMap.
# When absent (no .env / no CI secrets), the fallback provides e2e-fake.
- kind: ConfigMap
name: ukc-credentials-fallback
valuesKey: values.yaml
- kind: Secret
name: ukc-credentials
valuesKey: values.yaml
optional: true
8 changes: 8 additions & 0 deletions config/dependencies/unikraft-k8s-operator/helmrepository.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: unikraft-cloud
spec:
type: oci
interval: 1h
url: oci://ghcr.io/unikraft-cloud/helm-charts
8 changes: 8 additions & 0 deletions config/dependencies/unikraft-k8s-operator/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: ukc-operator
resources:
- namespace.yaml
- helmrepository.yaml
- helmrelease.yaml
- ukc-credentials-fallback.yaml
4 changes: 4 additions & 0 deletions config/dependencies/unikraft-k8s-operator/namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: ukc-operator
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ukc-credentials-fallback
data:
values.yaml: |
ukc:
metro: e2e-fake
token: e2e-fake
15 changes: 13 additions & 2 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,19 @@ spec:
- command:
- /manager
args:
- --leader-elect
- --health-probe-bind-address=:8081
- --leader-elect=$(LEADER_ELECT)
- --leader-elect-namespace=$(LEADER_ELECT_NAMESPACE)
- --health-probe-bind-address=$(HEALTH_PROBE_BIND_ADDRESS)
- --server-config=$(SERVER_CONFIG)
env:
- name: LEADER_ELECT
value: "true"
- name: LEADER_ELECT_NAMESPACE
value: ""
- name: HEALTH_PROBE_BIND_ADDRESS
value: ":8081"
- name: SERVER_CONFIG
value: ""
image: controller:latest
name: manager
securityContext:
Expand Down
14 changes: 14 additions & 0 deletions config/overlays/test-infra/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Example: Upstream and downstream are the SAME cluster (for development)
apiVersion: apiserver.config.datumapis.com/v1alpha1
kind: UnikraftProvider
metricsServer:
bindAddress: "0"
secureServing: false
discovery:
mode: single
downstreamResourceManagement:
# Empty kubeconfigPath means use the same cluster as upstream
kubeconfigPath: ""
managedResourceLabels:
managed-by: "infra-provider-unikraft"
locationClassName: "self-managed"
24 changes: 24 additions & 0 deletions config/overlays/test-infra/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: infra-provider-unikraft-system
resources:
- ../../default

images:
- name: controller
newName: ghcr.io/datum-cloud/unikraft-provider
newTag: dev

generatorOptions:
disableNameSuffixHash: true

configMapGenerator:
- name: manager-config
files:
- config.yaml=config.yaml

patches:
- path: patches/manager-config.yaml
target:
kind: Deployment
name: controller-manager
Loading
Loading