From 90de6613028eb8d68842faa409b533518451aa77 Mon Sep 17 00:00:00 2001 From: simontesar Date: Tue, 27 Oct 2026 07:56:37 +0200 Subject: [PATCH] chore: remove unused infrastructure folder --- .gitignore | 4 - README.md | 11 +- config/metal-operator/ignition-template.yaml | 56 ------ config/metal-operator/kustomization.yaml | 28 --- config/metal-operator/macdb-secret.yaml | 9 - config/metal-operator/manager_patch.yaml | 42 ----- config/metal-operator/metaldata_patch.yaml | 11 -- config/metal-operator/registry_service.yaml | 14 -- .../clusterrole.yaml | 51 ------ .../clusterrolebinding.yaml | 15 -- .../deployment.yaml | 62 ------- .../kustomization.yaml | 15 -- .../serviceaccount.yaml | 7 - .../components/go-mockup/bmc.yaml | 20 --- .../components/go-mockup/bmcsecret.yaml | 10 -- .../components/go-mockup/deployment.yaml | 53 ------ .../components/go-mockup/kustomization.yaml | 13 -- .../components/go-mockup/service.yaml | 13 -- .../components/mockup/bmc.yaml | 20 --- .../components/mockup/bmcsecret.yaml | 10 -- .../components/mockup/certificate.yaml | 15 -- .../components/mockup/deployment.yaml | 63 ------- .../components/mockup/kustomization.yaml | 9 - .../components/mockup/service.yaml | 13 -- .../instances/basic-go/kustomization.yaml | 57 ------- .../instances/basic/kustomization.yaml | 115 ------------- .../instances/contoso-go/kustomization.yaml | 66 -------- .../instances/gpu-dpu-go/kustomization.yaml | 57 ------- .../instances/gpu-dpu/kustomization.yaml | 115 ------------- .../instances/r660-go/kustomization.yaml | 64 ------- .../instances/r660/kustomization.yaml | 107 ------------ .../instances/r770-go/kustomization.yaml | 57 ------- .../instances/r770/kustomization.yaml | 115 ------------- .../instances/r7725-go/kustomization.yaml | 57 ------- .../instances/r7725/kustomization.yaml | 115 ------------- .../instances/xe9712-go/kustomization.yaml | 57 ------- .../instances/xe9712/kustomization.yaml | 115 ------------- config/redfish-mockups/kustomization.yaml | 17 -- environments.md | 26 --- infra/kind/Makefile | 159 ------------------ infra/kind/README.md | 74 -------- .../download-redfish-mockup-clients.sh | 40 ----- infra/kind/values-basic-go.yaml | 9 - infra/kind/values-contoso-go.yaml | 9 - infra/local/.env | 12 -- infra/local/.envrc | 3 - infra/local/.gitignore | 2 - infra/local/Makefile | 75 --------- infra/local/README.md | 14 -- infra/local/Vagrantfile | 83 --------- infra/local/group_vars/master.yaml | 15 -- infra/local/network-architecture.drawio.png | Bin 45828 -> 0 bytes infra/local/scripts/provision-k3s.sh | 26 --- infra/local/scripts/provision-master.sh | 44 ----- infra/local/scripts/provision-node.sh | 30 ---- infra/local/scripts/setup-host-vlans.sh | 82 --------- infra/playbooks/group_vars/all.yml | 2 - infra/playbooks/master.yaml | 103 ------------ infra/playbooks/templates/dhcp.conf.j2 | 16 -- redfish-mockup-clients/.gitkeep | 0 60 files changed, 5 insertions(+), 2497 deletions(-) delete mode 100644 config/metal-operator/ignition-template.yaml delete mode 100644 config/metal-operator/kustomization.yaml delete mode 100644 config/metal-operator/macdb-secret.yaml delete mode 100644 config/metal-operator/manager_patch.yaml delete mode 100644 config/metal-operator/metaldata_patch.yaml delete mode 100644 config/metal-operator/registry_service.yaml delete mode 100644 config/metalprobe-mock-controller/clusterrole.yaml delete mode 100644 config/metalprobe-mock-controller/clusterrolebinding.yaml delete mode 100644 config/metalprobe-mock-controller/deployment.yaml delete mode 100644 config/metalprobe-mock-controller/kustomization.yaml delete mode 100644 config/metalprobe-mock-controller/serviceaccount.yaml delete mode 100644 config/redfish-mockups/components/go-mockup/bmc.yaml delete mode 100644 config/redfish-mockups/components/go-mockup/bmcsecret.yaml delete mode 100644 config/redfish-mockups/components/go-mockup/deployment.yaml delete mode 100644 config/redfish-mockups/components/go-mockup/kustomization.yaml delete mode 100644 config/redfish-mockups/components/go-mockup/service.yaml delete mode 100644 config/redfish-mockups/components/mockup/bmc.yaml delete mode 100644 config/redfish-mockups/components/mockup/bmcsecret.yaml delete mode 100644 config/redfish-mockups/components/mockup/certificate.yaml delete mode 100644 config/redfish-mockups/components/mockup/deployment.yaml delete mode 100644 config/redfish-mockups/components/mockup/kustomization.yaml delete mode 100644 config/redfish-mockups/components/mockup/service.yaml delete mode 100644 config/redfish-mockups/instances/basic-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/basic/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/contoso-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/gpu-dpu-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/gpu-dpu/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/r660-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/r660/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/r770-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/r770/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/r7725-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/r7725/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/xe9712-go/kustomization.yaml delete mode 100644 config/redfish-mockups/instances/xe9712/kustomization.yaml delete mode 100644 config/redfish-mockups/kustomization.yaml delete mode 100644 environments.md delete mode 100644 infra/kind/Makefile delete mode 100644 infra/kind/README.md delete mode 100755 infra/kind/scripts/download-redfish-mockup-clients.sh delete mode 100644 infra/kind/values-basic-go.yaml delete mode 100644 infra/kind/values-contoso-go.yaml delete mode 100644 infra/local/.env delete mode 100644 infra/local/.envrc delete mode 100644 infra/local/.gitignore delete mode 100644 infra/local/Makefile delete mode 100644 infra/local/README.md delete mode 100644 infra/local/Vagrantfile delete mode 100644 infra/local/group_vars/master.yaml delete mode 100644 infra/local/network-architecture.drawio.png delete mode 100755 infra/local/scripts/provision-k3s.sh delete mode 100755 infra/local/scripts/provision-master.sh delete mode 100755 infra/local/scripts/provision-node.sh delete mode 100755 infra/local/scripts/setup-host-vlans.sh delete mode 100644 infra/playbooks/group_vars/all.yml delete mode 100644 infra/playbooks/master.yaml delete mode 100644 infra/playbooks/templates/dhcp.conf.j2 delete mode 100644 redfish-mockup-clients/.gitkeep diff --git a/.gitignore b/.gitignore index f8ff2e4..1974b92 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1 @@ .envrc.local -infra/local/.vagrant/ -infra/local/kubeconfig -infra/kind/kubeconfig.yaml -redfish-mockup-clients diff --git a/README.md b/README.md index 93ce9d4..e24fb37 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,16 @@ The `tests` directory contains a suite of tests based on [chainsaw](https://kyve * A metal-operator installation and BMC to run tests against. This repository usually uses the locally virtualised [metal-lab](https://github.com/simontesar/metal-lab) to develop or verify functionality of the actual tests. You can use the lab setup as a reference. ### Usage -The server to run a test against is configured by passing a values file to chainsaw via `VALUES`. There is no default, tests fail unless `VALUES` is set. To just see the suite run, use `infra/kind/values-basic-go.yaml`, which points to a Redfish mock setup in the [`kind` environment](environments.md). +The server to run a test against is configured by passing a values file to chainsaw via `VALUES`. To try the tests without using your own BMC, clone the [`metal-lab`](https://github.com/simontesar/metal-lab) repository and refer to its `README` to bring it up. ```bash # Examples -make test VALUES=infra/kind/values-basic-go.yaml # Run all tests -make test/01-bmc-registration VALUES=infra/kind/values-basic-go.yaml # Run a specific test -make test/03-power-annotation VALUES=/path/to/metal-lab/values-containerlab-node1.yaml # Run against a specific BMC +export KUBECONFIG=/path/to/metal-lab/kubeconfig.yaml +make test VALUES=/path/to/metal-lab/values-containerlab-node1.yaml # Run all tests +make test/01-bmc-registration VALUES=/path/to/metal-lab/values-containerlab-node1.yaml # Run a specific test +make test/03-power-annotation VALUES=/path/to/your-bmc.yaml # Run against your own BMC ``` -The [`metal-lab`](https://github.com/simontesar/metal-lab) repository provides a standalone containerlab-based environment and ships its own `VALUES` `values-containerlab-node1.yaml` / `values-containerlab-node2.yaml`. Clone the metal-lab repository and refer to its `README` to try the suite of tests without your own BMC. - ### Bring your own BMC To run tests against your own BMC, copy these values into a new file: ```yaml diff --git a/config/metal-operator/ignition-template.yaml b/config/metal-operator/ignition-template.yaml deleted file mode 100644 index 0b2c482..0000000 --- a/config/metal-operator/ignition-template.yaml +++ /dev/null @@ -1,56 +0,0 @@ -variant: fcos -version: "1.3.0" -systemd: - units: - - name: var-lib-containerd.mount - enabled: true - contents: |- - [Unit] - Description=tmpfs for containerd image cache - DefaultDependencies=no - Before=containerd.service - - [Mount] - What=tmpfs - Where=/var/lib/containerd - Type=tmpfs - Options=mode=0700,size=4g - - [Install] - WantedBy=multi-user.target - - name: containerd.service - enabled: true - dropins: - - name: 10-wait-mount.conf - contents: |- - [Unit] - After=var-lib-containerd.mount - Requires=var-lib-containerd.mount - - name: metalprobe.service - enabled: true - contents: |- - [Unit] - Description=Run Metalprobe Container - After=containerd.service - Requires=containerd.service - [Service] - Restart=on-failure - RestartSec=20 - # --skip-metadata skips fetching platform manifests not needed locally; requires containerd >= 1.4 - ExecStartPre=/usr/bin/ctr images pull --skip-metadata {{.Image}} - ExecStartPre=-/usr/bin/ctr tasks delete --force metalprobe - ExecStartPre=-/usr/bin/ctr containers delete metalprobe - ExecStart=/usr/bin/ctr run --rm --net-host --privileged {{.Image}} metalprobe ./launch.sh {{.Flags}} - TimeoutSec=600 - [Install] - WantedBy=multi-user.target -storage: - files: [] -passwd: - users: - - name: root - password_hash: "$6$U13XNGV9MMTY3xbZ$CoTJBLmGNKn7We/0FpgtURNGudhpKXm/S9E5qXa5hV4RXmnviJJXlKHuZwGSLU5ZxkI0PYMWk.coIjoVL1ADN0" - - name: metal - password_hash: {{.PasswordHash}} - groups: [ "wheel" ] - ssh_authorized_keys: [ {{.SSHPublicKey}} ] diff --git a/config/metal-operator/kustomization.yaml b/config/metal-operator/kustomization.yaml deleted file mode 100644 index ce7dde7..0000000 --- a/config/metal-operator/kustomization.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- https://github.com/ironcore-dev/metal-operator//config/default?ref=35a86bac04c01208a3fb6593b498388590d05f5b -- registry_service.yaml -- macdb-secret.yaml - -configMapGenerator: -- name: ignition-template - namespace: metal-operator-system - files: - - ignition-template.yaml - -generatorOptions: - disableNameSuffixHash: true - -patches: -- path: manager_patch.yaml -- path: metaldata_patch.yaml - -images: -- name: controller - newName: controller - newTag: latest -- name: metaldata - newName: metaldata - newTag: latest diff --git a/config/metal-operator/macdb-secret.yaml b/config/metal-operator/macdb-secret.yaml deleted file mode 100644 index 93eb87e..0000000 --- a/config/metal-operator/macdb-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: macdb - namespace: metal-operator-system -type: Opaque -stringData: - mac_prefixes.yaml: | - macPrefixes: [] diff --git a/config/metal-operator/manager_patch.yaml b/config/metal-operator/manager_patch.yaml deleted file mode 100644 index 778d22d..0000000 --- a/config/metal-operator/manager_patch.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - imagePullPolicy: IfNotPresent - args: - - --leader-elect - - --metrics-bind-address=:8443 - - --health-probe-bind-address=:8081 - - --mac-prefixes-file=/etc/macdb/mac_prefixes.yaml - - --probe-image=ghcr.io/ironcore-dev/metalprobe:latest - #- --probe-os-image=ghcr.io/ironcore-dev/gardenlinux:2150.0.0-metal-manual-a0ea39fa - - --probe-os-image=ghcr.io/ironcore-dev/gardenlinux/capi:2150.0.0-metal - - --registry-url=http://metal-registry.metal-operator-system.svc:30000 - - --registry-port=30000 - - --skip-cert-validation - - --bmc-reset-waiting-interval=1s - ports: - - containerPort: 8081 - name: health - protocol: TCP - - containerPort: 30000 - volumeMounts: - - mountPath: /etc/macdb/ - name: macdb - - mountPath: /etc/metal-operator - name: ignition-template - readOnly: true - volumes: - - name: macdb - secret: - defaultMode: 420 - secretName: macdb - - name: ignition-template - configMap: - name: ignition-template diff --git a/config/metal-operator/metaldata_patch.yaml b/config/metal-operator/metaldata_patch.yaml deleted file mode 100644 index 49f12e9..0000000 --- a/config/metal-operator/metaldata_patch.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: metaldata - namespace: system -spec: - template: - spec: - containers: - - name: metaldata - imagePullPolicy: IfNotPresent diff --git a/config/metal-operator/registry_service.yaml b/config/metal-operator/registry_service.yaml deleted file mode 100644 index 2e0c4ec..0000000 --- a/config/metal-operator/registry_service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: metal-registry - namespace: metal-operator-system -spec: - type: NodePort - ports: - - name: registry-server - port: 30000 - targetPort: 30000 - nodePort: 30000 - selector: - control-plane: controller-manager diff --git a/config/metalprobe-mock-controller/clusterrole.yaml b/config/metalprobe-mock-controller/clusterrole.yaml deleted file mode 100644 index 27ea683..0000000 --- a/config/metalprobe-mock-controller/clusterrole.yaml +++ /dev/null @@ -1,51 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: metalprobe-mock-controller - labels: - app.kubernetes.io/name: metalprobe-mock-controller - app.kubernetes.io/managed-by: kustomize -rules: -- apiGroups: - - metal.ironcore.dev - resources: - - serverbootconfigurations - verbs: - - get - - list - - watch -- apiGroups: - - metal.ironcore.dev - resources: - - serverbootconfigurations/status - verbs: - - get - - update - - patch -- apiGroups: - - metal.ironcore.dev - resources: - - servers - verbs: - - get - - list - - watch -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch diff --git a/config/metalprobe-mock-controller/clusterrolebinding.yaml b/config/metalprobe-mock-controller/clusterrolebinding.yaml deleted file mode 100644 index cce17c2..0000000 --- a/config/metalprobe-mock-controller/clusterrolebinding.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: metalprobe-mock-controller - labels: - app.kubernetes.io/name: metalprobe-mock-controller - app.kubernetes.io/managed-by: kustomize -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: metalprobe-mock-controller -subjects: -- kind: ServiceAccount - name: metalprobe-mock-controller - namespace: metal-operator-system diff --git a/config/metalprobe-mock-controller/deployment.yaml b/config/metalprobe-mock-controller/deployment.yaml deleted file mode 100644 index 75bd340..0000000 --- a/config/metalprobe-mock-controller/deployment.yaml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: metalprobe-mock-controller - labels: - app.kubernetes.io/name: metalprobe-mock-controller - app.kubernetes.io/managed-by: kustomize -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: metalprobe-mock-controller - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - app.kubernetes.io/name: metalprobe-mock-controller - spec: - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - containers: - - name: manager - image: metalprobe-mock-controller:latest - imagePullPolicy: IfNotPresent - command: - - /metalprobe-mock-controller - args: - - --leader-elect - - --registry-url=http://metal-registry.metal-operator-system.svc:30000 - ports: - - containerPort: 8081 - name: health - protocol: TCP - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 10m - memory: 64Mi - serviceAccountName: metalprobe-mock-controller - terminationGracePeriodSeconds: 10 diff --git a/config/metalprobe-mock-controller/kustomization.yaml b/config/metalprobe-mock-controller/kustomization.yaml deleted file mode 100644 index 714ac0f..0000000 --- a/config/metalprobe-mock-controller/kustomization.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -resources: -- serviceaccount.yaml -- clusterrole.yaml -- clusterrolebinding.yaml -- deployment.yaml - -images: -- name: metalprobe-mock-controller - newName: metalprobe-mock-controller - newTag: latest diff --git a/config/metalprobe-mock-controller/serviceaccount.yaml b/config/metalprobe-mock-controller/serviceaccount.yaml deleted file mode 100644 index b8ef67f..0000000 --- a/config/metalprobe-mock-controller/serviceaccount.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: metalprobe-mock-controller - labels: - app.kubernetes.io/name: metalprobe-mock-controller - app.kubernetes.io/managed-by: kustomize diff --git a/config/redfish-mockups/components/go-mockup/bmc.yaml b/config/redfish-mockups/components/go-mockup/bmc.yaml deleted file mode 100644 index 8349431..0000000 --- a/config/redfish-mockups/components/go-mockup/bmc.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: metal.ironcore.dev/v1alpha1 -kind: BMC -metadata: - name: mockup - labels: - app.kubernetes.io/name: redfish-go-mockup - app.kubernetes.io/component: redfish-go-mockup -spec: - bmcSecretRef: - name: PLACEHOLDER_BMC_SECRET_NAME - hostname: PLACEHOLDER_HOSTNAME - consoleProtocol: - name: SSH - port: 22 - access: - ip: PLACEHOLDER_BMC_IP - protocol: - name: Redfish - port: 8000 - scheme: http diff --git a/config/redfish-mockups/components/go-mockup/bmcsecret.yaml b/config/redfish-mockups/components/go-mockup/bmcsecret.yaml deleted file mode 100644 index fd1c65a..0000000 --- a/config/redfish-mockups/components/go-mockup/bmcsecret.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: metal.ironcore.dev/v1alpha1 -kind: BMCSecret -metadata: - name: mockup - labels: - app.kubernetes.io/name: redfish-go-mockup - app.kubernetes.io/component: redfish-go-mockup -stringData: - username: PLACEHOLDER_USERNAME - password: PLACEHOLDER_PASSWORD diff --git a/config/redfish-mockups/components/go-mockup/deployment.yaml b/config/redfish-mockups/components/go-mockup/deployment.yaml deleted file mode 100644 index a5703b7..0000000 --- a/config/redfish-mockups/components/go-mockup/deployment.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mockup - labels: - app.kubernetes.io/name: redfish-go-mockup - app.kubernetes.io/component: redfish-go-mockup -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: redfish-go-mockup - app.kubernetes.io/component: redfish-go-mockup - template: - metadata: - labels: - app.kubernetes.io/name: redfish-go-mockup - app.kubernetes.io/component: redfish-go-mockup - spec: - containers: - - name: mock-server - image: mock-server:latest - imagePullPolicy: IfNotPresent - args: - - -addr - - :8000 - - -data - - /clients/PLACEHOLDER_CLIENT/redfish/v1 - ports: - - containerPort: 8000 - volumeMounts: - - name: clients - mountPath: /clients - readOnly: true - livenessProbe: - httpGet: - path: /redfish/v1 - port: 8000 - scheme: HTTP - initialDelaySeconds: 15 - periodSeconds: 10 - readinessProbe: - httpGet: - path: /redfish/v1 - port: 8000 - scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: clients - hostPath: - path: PLACEHOLDER_CLIENTS_MOUNT - type: Directory diff --git a/config/redfish-mockups/components/go-mockup/kustomization.yaml b/config/redfish-mockups/components/go-mockup/kustomization.yaml deleted file mode 100644 index aaf34e7..0000000 --- a/config/redfish-mockups/components/go-mockup/kustomization.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -resources: -- deployment.yaml -- service.yaml -- bmc.yaml -- bmcsecret.yaml - -images: -- name: mock-server - newName: mock-server - newTag: latest diff --git a/config/redfish-mockups/components/go-mockup/service.yaml b/config/redfish-mockups/components/go-mockup/service.yaml deleted file mode 100644 index 1faebe0..0000000 --- a/config/redfish-mockups/components/go-mockup/service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mockup -spec: - clusterIP: 10.96.200.20 - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - selector: - app.kubernetes.io/name: redfish-go-mockup - app.kubernetes.io/component: redfish-go-mockup diff --git a/config/redfish-mockups/components/mockup/bmc.yaml b/config/redfish-mockups/components/mockup/bmc.yaml deleted file mode 100644 index 8456d00..0000000 --- a/config/redfish-mockups/components/mockup/bmc.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: metal.ironcore.dev/v1alpha1 -kind: BMC -metadata: - name: mockup - labels: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup -spec: - bmcSecretRef: - name: PLACEHOLDER_BMC_SECRET_NAME - hostname: PLACEHOLDER_HOSTNAME - consoleProtocol: - name: SSH - port: 22 - access: - ip: PLACEHOLDER_BMC_IP - protocol: - name: Redfish - port: 8000 - scheme: https diff --git a/config/redfish-mockups/components/mockup/bmcsecret.yaml b/config/redfish-mockups/components/mockup/bmcsecret.yaml deleted file mode 100644 index 23ec99d..0000000 --- a/config/redfish-mockups/components/mockup/bmcsecret.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: metal.ironcore.dev/v1alpha1 -kind: BMCSecret -metadata: - name: mockup - labels: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup -stringData: - username: PLACEHOLDER_USERNAME - password: PLACEHOLDER_PASSWORD diff --git a/config/redfish-mockups/components/mockup/certificate.yaml b/config/redfish-mockups/components/mockup/certificate.yaml deleted file mode 100644 index f0667b5..0000000 --- a/config/redfish-mockups/components/mockup/certificate.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: tls - labels: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup -spec: - dnsNames: - - SERVICE_NAME.SERVICE_NAMESPACE.svc - - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local - issuerRef: - kind: Issuer - name: metal-operator-selfsigned-issuer - secretName: PLACEHOLDER_TLS_SECRET diff --git a/config/redfish-mockups/components/mockup/deployment.yaml b/config/redfish-mockups/components/mockup/deployment.yaml deleted file mode 100644 index b3105c3..0000000 --- a/config/redfish-mockups/components/mockup/deployment.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mockup - labels: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup - template: - metadata: - labels: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup - spec: - containers: - - name: mockup - image: docker.io/dmtf/redfish-mockup-server:latest - args: - - "-D" - - "/clients/PLACEHOLDER_CLIENT" - - "--ssl" - - "--cert" - - "/certs/tls.crt" - - "--key" - - "/certs/tls.key" - - "-p" - - "8000" - ports: - - containerPort: 8000 - volumeMounts: - - name: clients - mountPath: /clients - readOnly: true - - name: tls - mountPath: /certs - readOnly: true - livenessProbe: - httpGet: - path: /redfish/v1 - port: 8000 - scheme: HTTPS - initialDelaySeconds: 15 - periodSeconds: 10 - readinessProbe: - httpGet: - path: /redfish/v1 - port: 8000 - scheme: HTTPS - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: clients - hostPath: - path: PLACEHOLDER_CLIENTS_MOUNT - type: Directory - - name: tls - secret: - secretName: PLACEHOLDER_TLS_SECRET diff --git a/config/redfish-mockups/components/mockup/kustomization.yaml b/config/redfish-mockups/components/mockup/kustomization.yaml deleted file mode 100644 index 49abbea..0000000 --- a/config/redfish-mockups/components/mockup/kustomization.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -resources: -- deployment.yaml -- service.yaml -- certificate.yaml -- bmc.yaml -- bmcsecret.yaml diff --git a/config/redfish-mockups/components/mockup/service.yaml b/config/redfish-mockups/components/mockup/service.yaml deleted file mode 100644 index bd28501..0000000 --- a/config/redfish-mockups/components/mockup/service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mockup -spec: - clusterIP: 10.96.200.10 - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - selector: - app.kubernetes.io/name: redfish-mockup - app.kubernetes.io/component: redfish-mockup diff --git a/config/redfish-mockups/instances/basic-go/kustomization.yaml b/config/redfish-mockups/instances/basic-go/kustomization.yaml deleted file mode 100644 index dbe7fab..0000000 --- a/config/redfish-mockups/instances/basic-go/kustomization.yaml +++ /dev/null @@ -1,57 +0,0 @@ -# Instance overlay for the iDRAC basic config Go mockup client. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-basic-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: basic-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.25 -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/3 - value: /clients/iDRAC_mockup_client_basic_config/redfish/v1 - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-basic-go-mockup - - op: replace - path: /spec/hostname - value: dell-basic-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.25 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/basic/kustomization.yaml b/config/redfish-mockups/instances/basic/kustomization.yaml deleted file mode 100644 index d9e5eb6..0000000 --- a/config/redfish-mockups/instances/basic/kustomization.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# Instance overlay for the iDRAC basic config mockup client. -# -# PLACEHOLDER_CLIENT -> /clients/iDRAC_mockup_client_basic_config -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_TLS_SECRET -> redfish-basic-tls -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-basic-mockup -# PLACEHOLDER_HOSTNAME -> dell-basic-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.15 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/mockup - -namePrefix: redfish-basic- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: basic - -patches: -# Resolves PLACEHOLDER_BMC_IP (Service clusterIP) -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.15 -# Resolves PLACEHOLDER_CLIENT, PLACEHOLDER_CLIENTS_MOUNT, and -# PLACEHOLDER_TLS_SECRET -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/1 - value: /clients/iDRAC_mockup_client_basic_config - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients - - op: replace - path: /spec/template/spec/volumes/1/secret/secretName - value: redfish-basic-tls -# Resolves PLACEHOLDER_TLS_SECRET -- target: - kind: Certificate - name: tls - patch: |- - - op: replace - path: /spec/secretName - value: redfish-basic-tls -# Resolves BMC placeholders -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-basic-mockup - - op: replace - path: /spec/hostname - value: dell-basic-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.15 -# Resolves BMCSecret credential placeholders -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar - -replacements: -# Resolves SERVICE_NAME -- source: - kind: Service - name: mockup - fieldPath: metadata.name - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 0 - create: true -# Resolves SERVICE_NAMESPACE -- source: - kind: Service - name: mockup - fieldPath: metadata.namespace - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 1 - create: true diff --git a/config/redfish-mockups/instances/contoso-go/kustomization.yaml b/config/redfish-mockups/instances/contoso-go/kustomization.yaml deleted file mode 100644 index acff1bd..0000000 --- a/config/redfish-mockups/instances/contoso-go/kustomization.yaml +++ /dev/null @@ -1,66 +0,0 @@ -# Instance overlay for the built-in Contoso Go mockup (embedded data). -# -# No -data flag and no hostPath mount -> the server uses its embedded -# Contoso Redfish data served at /redfish/v1 over HTTP. -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-contoso-go-mockup -# PLACEHOLDER_HOSTNAME -> contoso-go-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.26 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-contoso-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: contoso-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.26 -- target: - kind: Deployment - name: mockup - patch: |- - - op: remove - path: /spec/template/spec/containers/0/args/3 - - op: remove - path: /spec/template/spec/containers/0/args/2 - - op: remove - path: /spec/template/spec/containers/0/volumeMounts - - op: remove - path: /spec/template/spec/volumes -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-contoso-go-mockup - - op: replace - path: /spec/hostname - value: contoso-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.26 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/gpu-dpu-go/kustomization.yaml b/config/redfish-mockups/instances/gpu-dpu-go/kustomization.yaml deleted file mode 100644 index 3a9d4b1..0000000 --- a/config/redfish-mockups/instances/gpu-dpu-go/kustomization.yaml +++ /dev/null @@ -1,57 +0,0 @@ -# Instance overlay for the iDRAC GPU/DPU config Go mockup client. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-gpu-dpu-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: gpu-dpu-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.24 -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/3 - value: /clients/iDRAC_mockup_client_GPU_DPU_config/redfish/v1 - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-gpu-dpu-go-mockup - - op: replace - path: /spec/hostname - value: dell-gpu-dpu-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.24 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/gpu-dpu/kustomization.yaml b/config/redfish-mockups/instances/gpu-dpu/kustomization.yaml deleted file mode 100644 index 1ef1af2..0000000 --- a/config/redfish-mockups/instances/gpu-dpu/kustomization.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# Instance overlay for the iDRAC GPU/DPU config mockup client. -# -# PLACEHOLDER_CLIENT -> /clients/iDRAC_mockup_client_GPU_DPU_config -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_TLS_SECRET -> redfish-gpu-dpu-tls -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-gpu-dpu-mockup -# PLACEHOLDER_HOSTNAME -> dell-gpu-dpu-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.14 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/mockup - -namePrefix: redfish-gpu-dpu- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: gpu-dpu - -patches: -# Resolves PLACEHOLDER_BMC_IP (Service clusterIP) -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.14 -# Resolves PLACEHOLDER_CLIENT, PLACEHOLDER_CLIENTS_MOUNT, and -# PLACEHOLDER_TLS_SECRET -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/1 - value: /clients/iDRAC_mockup_client_GPU_DPU_config - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients - - op: replace - path: /spec/template/spec/volumes/1/secret/secretName - value: redfish-gpu-dpu-tls -# Resolves PLACEHOLDER_TLS_SECRET -- target: - kind: Certificate - name: tls - patch: |- - - op: replace - path: /spec/secretName - value: redfish-gpu-dpu-tls -# Resolves BMC placeholders -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-gpu-dpu-mockup - - op: replace - path: /spec/hostname - value: dell-gpu-dpu-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.14 -# Resolves BMCSecret credential placeholders -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar - -replacements: -# Resolves SERVICE_NAME -- source: - kind: Service - name: mockup - fieldPath: metadata.name - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 0 - create: true -# Resolves SERVICE_NAMESPACE -- source: - kind: Service - name: mockup - fieldPath: metadata.namespace - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 1 - create: true diff --git a/config/redfish-mockups/instances/r660-go/kustomization.yaml b/config/redfish-mockups/instances/r660-go/kustomization.yaml deleted file mode 100644 index ac5d77d..0000000 --- a/config/redfish-mockups/instances/r660-go/kustomization.yaml +++ /dev/null @@ -1,64 +0,0 @@ -# Instance overlay for the R660xs iDRAC Go mockup client. -# -# -data path -> /clients/R660xs_iDRAC9_7_20_10_05_mockup_client/redfish/v1 -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-r660-go-mockup -# PLACEHOLDER_HOSTNAME -> dell-r660xs-go-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.20 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-r660-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: r660-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.20 -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/3 - value: /clients/R660xs_iDRAC9_7_20_10_05_mockup_client/redfish/v1 - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-r660-go-mockup - - op: replace - path: /spec/hostname - value: dell-r660xs-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.20 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/r660/kustomization.yaml b/config/redfish-mockups/instances/r660/kustomization.yaml deleted file mode 100644 index 86f3124..0000000 --- a/config/redfish-mockups/instances/r660/kustomization.yaml +++ /dev/null @@ -1,107 +0,0 @@ -# Instance overlay for the R660xs iDRAC mockup client. -# -# PLACEHOLDER_CLIENT -> /clients/R660xs_iDRAC9_7_20_10_05_mockup_client -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_TLS_SECRET -> redfish-r660-tls -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-r660-mockup -# PLACEHOLDER_HOSTNAME -> dell-r660xs-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.10 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/mockup - -namePrefix: redfish-r660- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: r660 - -patches: -# Resolves PLACEHOLDER_CLIENT, PLACEHOLDER_CLIENTS_MOUNT, and -# PLACEHOLDER_TLS_SECRET -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/1 - value: /clients/R660xs_iDRAC9_7_20_10_05_mockup_client - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients - - op: replace - path: /spec/template/spec/volumes/1/secret/secretName - value: redfish-r660-tls -# Resolves PLACEHOLDER_TLS_SECRET -- target: - kind: Certificate - name: tls - patch: |- - - op: replace - path: /spec/secretName - value: redfish-r660-tls -# Resolves BMC placeholders -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-r660-mockup - - op: replace - path: /spec/hostname - value: dell-r660xs-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.10 -# Resolves BMCSecret credential placeholders -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar - -replacements: -# Resolves SERVICE_NAME -- source: - kind: Service - name: mockup - fieldPath: metadata.name - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 0 - create: true -# Resolves SERVICE_NAMESPACE -- source: - kind: Service - name: mockup - fieldPath: metadata.namespace - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 1 - create: true diff --git a/config/redfish-mockups/instances/r770-go/kustomization.yaml b/config/redfish-mockups/instances/r770-go/kustomization.yaml deleted file mode 100644 index 580e427..0000000 --- a/config/redfish-mockups/instances/r770-go/kustomization.yaml +++ /dev/null @@ -1,57 +0,0 @@ -# Instance overlay for the R770 iDRAC Go mockup client. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-r770-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: r770-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.21 -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/3 - value: /clients/R770_iDRAC10_1_10_17_00_mockup_client/redfish/v1 - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-r770-go-mockup - - op: replace - path: /spec/hostname - value: dell-r770-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.21 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/r770/kustomization.yaml b/config/redfish-mockups/instances/r770/kustomization.yaml deleted file mode 100644 index b177167..0000000 --- a/config/redfish-mockups/instances/r770/kustomization.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# Instance overlay for the R770 iDRAC mockup client. -# -# PLACEHOLDER_CLIENT -> /clients/R770_iDRAC10_1_10_17_00_mockup_client -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_TLS_SECRET -> redfish-r770-tls -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-r770-mockup -# PLACEHOLDER_HOSTNAME -> dell-r770-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.11 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/mockup - -namePrefix: redfish-r770- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: r770 - -patches: -# Resolves PLACEHOLDER_BMC_IP (Service clusterIP) -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.11 -# Resolves PLACEHOLDER_CLIENT, PLACEHOLDER_CLIENTS_MOUNT, and -# PLACEHOLDER_TLS_SECRET -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/1 - value: /clients/R770_iDRAC10_1_10_17_00_mockup_client - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients - - op: replace - path: /spec/template/spec/volumes/1/secret/secretName - value: redfish-r770-tls -# Resolves PLACEHOLDER_TLS_SECRET -- target: - kind: Certificate - name: tls - patch: |- - - op: replace - path: /spec/secretName - value: redfish-r770-tls -# Resolves BMC placeholders -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-r770-mockup - - op: replace - path: /spec/hostname - value: dell-r770-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.11 -# Resolves BMCSecret credential placeholders -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar - -replacements: -# Resolves SERVICE_NAME -- source: - kind: Service - name: mockup - fieldPath: metadata.name - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 0 - create: true -# Resolves SERVICE_NAMESPACE -- source: - kind: Service - name: mockup - fieldPath: metadata.namespace - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 1 - create: true diff --git a/config/redfish-mockups/instances/r7725-go/kustomization.yaml b/config/redfish-mockups/instances/r7725-go/kustomization.yaml deleted file mode 100644 index 2d979e7..0000000 --- a/config/redfish-mockups/instances/r7725-go/kustomization.yaml +++ /dev/null @@ -1,57 +0,0 @@ -# Instance overlay for the R7725 iDRAC Go mockup client. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-r7725-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: r7725-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.22 -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/3 - value: /clients/R7725_iDRAC10_1_20_70_50_mockup_client/redfish/v1 - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-r7725-go-mockup - - op: replace - path: /spec/hostname - value: dell-r7725-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.22 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/r7725/kustomization.yaml b/config/redfish-mockups/instances/r7725/kustomization.yaml deleted file mode 100644 index 7b4dc79..0000000 --- a/config/redfish-mockups/instances/r7725/kustomization.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# Instance overlay for the R7725 iDRAC mockup client. -# -# PLACEHOLDER_CLIENT -> /clients/R7725_iDRAC10_1_20_70_50_mockup_client -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_TLS_SECRET -> redfish-r7725-tls -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-r7725-mockup -# PLACEHOLDER_HOSTNAME -> dell-r7725-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.12 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/mockup - -namePrefix: redfish-r7725- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: r7725 - -patches: -# Resolves PLACEHOLDER_BMC_IP (Service clusterIP) -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.12 -# Resolves PLACEHOLDER_CLIENT, PLACEHOLDER_CLIENTS_MOUNT, and -# PLACEHOLDER_TLS_SECRET -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/1 - value: /clients/R7725_iDRAC10_1_20_70_50_mockup_client - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients - - op: replace - path: /spec/template/spec/volumes/1/secret/secretName - value: redfish-r7725-tls -# Resolves PLACEHOLDER_TLS_SECRET -- target: - kind: Certificate - name: tls - patch: |- - - op: replace - path: /spec/secretName - value: redfish-r7725-tls -# Resolves BMC placeholders -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-r7725-mockup - - op: replace - path: /spec/hostname - value: dell-r7725-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.12 -# Resolves BMCSecret credential placeholders -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar - -replacements: -# Resolves SERVICE_NAME -- source: - kind: Service - name: mockup - fieldPath: metadata.name - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 0 - create: true -# Resolves SERVICE_NAMESPACE -- source: - kind: Service - name: mockup - fieldPath: metadata.namespace - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 1 - create: true diff --git a/config/redfish-mockups/instances/xe9712-go/kustomization.yaml b/config/redfish-mockups/instances/xe9712-go/kustomization.yaml deleted file mode 100644 index 84e8b72..0000000 --- a/config/redfish-mockups/instances/xe9712-go/kustomization.yaml +++ /dev/null @@ -1,57 +0,0 @@ -# Instance overlay for the XE9712 iDRAC Go mockup client. -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/go-mockup - -namePrefix: redfish-xe9712-go- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: xe9712-go - -patches: -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.23 -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/3 - value: /clients/XE9712_iDRAC10_1_30_07_10_mockup_client/redfish/v1 - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-xe9712-go-mockup - - op: replace - path: /spec/hostname - value: dell-xe9712-go-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.23 -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar diff --git a/config/redfish-mockups/instances/xe9712/kustomization.yaml b/config/redfish-mockups/instances/xe9712/kustomization.yaml deleted file mode 100644 index 9b7bb33..0000000 --- a/config/redfish-mockups/instances/xe9712/kustomization.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# Instance overlay for the XE9712 iDRAC mockup client. -# -# PLACEHOLDER_CLIENT -> /clients/XE9712_iDRAC10_1_30_07_10_mockup_client -# PLACEHOLDER_CLIENTS_MOUNT -> /redfish-clients -# PLACEHOLDER_TLS_SECRET -> redfish-xe9712-tls -# PLACEHOLDER_BMC_SECRET_NAME -> redfish-xe9712-mockup -# PLACEHOLDER_HOSTNAME -> dell-xe9712-mockup -# PLACEHOLDER_BMC_IP -> 10.96.200.13 -# PLACEHOLDER_USERNAME / PLACEHOLDER_PASSWORD -> foo / bar -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: metal-operator-system - -components: -- ../../components/mockup - -namePrefix: redfish-xe9712- - -labels: -- includeSelectors: true - pairs: - app.kubernetes.io/instance: xe9712 - -patches: -# Resolves PLACEHOLDER_BMC_IP (Service clusterIP) -- target: - kind: Service - name: mockup - patch: |- - - op: replace - path: /spec/clusterIP - value: 10.96.200.13 -# Resolves PLACEHOLDER_CLIENT, PLACEHOLDER_CLIENTS_MOUNT, and -# PLACEHOLDER_TLS_SECRET -- target: - kind: Deployment - name: mockup - patch: |- - - op: replace - path: /spec/template/spec/containers/0/args/1 - value: /clients/XE9712_iDRAC10_1_30_07_10_mockup_client - - op: replace - path: /spec/template/spec/volumes/0/hostPath/path - value: /redfish-clients - - op: replace - path: /spec/template/spec/volumes/1/secret/secretName - value: redfish-xe9712-tls -# Resolves PLACEHOLDER_TLS_SECRET -- target: - kind: Certificate - name: tls - patch: |- - - op: replace - path: /spec/secretName - value: redfish-xe9712-tls -# Resolves BMC placeholders -- target: - kind: BMC - name: mockup - patch: |- - - op: replace - path: /spec/bmcSecretRef/name - value: redfish-xe9712-mockup - - op: replace - path: /spec/hostname - value: dell-xe9712-mockup - - op: replace - path: /spec/access/ip - value: 10.96.200.13 -# Resolves BMCSecret credential placeholders -- target: - kind: BMCSecret - name: mockup - patch: |- - - op: replace - path: /stringData/username - value: foo - - op: replace - path: /stringData/password - value: bar - -replacements: -# Resolves SERVICE_NAME -- source: - kind: Service - name: mockup - fieldPath: metadata.name - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 0 - create: true -# Resolves SERVICE_NAMESPACE -- source: - kind: Service - name: mockup - fieldPath: metadata.namespace - targets: - - select: - kind: Certificate - name: tls - fieldPaths: - - spec.dnsNames.0 - - spec.dnsNames.1 - options: - delimiter: "." - index: 1 - create: true diff --git a/config/redfish-mockups/kustomization.yaml b/config/redfish-mockups/kustomization.yaml deleted file mode 100644 index b215ba1..0000000 --- a/config/redfish-mockups/kustomization.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- instances/r660 -- instances/r770 -- instances/r7725 -- instances/xe9712 -- instances/gpu-dpu -- instances/basic -- instances/r660-go -- instances/r770-go -- instances/r7725-go -- instances/xe9712-go -- instances/gpu-dpu-go -- instances/basic-go -- instances/contoso-go diff --git a/environments.md b/environments.md deleted file mode 100644 index 30ca40d..0000000 --- a/environments.md +++ /dev/null @@ -1,26 +0,0 @@ -# Environments - -This repository contains virtualised or containerised infrastructure environments that mock or emulate physical BMC/server nodes. They don't relate to running tests against a custom BMC. - -Refer to the `make help` target in every environment's subdirectory for usage. - -## Supporting Environments - -### KIND environment -Manages a [kind](https://kind.sigs.k8s.io/) cluster to run the metal-operator and its dependencies. To simulate BMCs and Servers, it runs a Go-based Redfish mock server (a modified version of the metal-operator's `bmc/mock/main.go`) that supports using system-specific Redfish client mock data like the [DMTF mockup server](https://github.com/DMTF/Redfish-Mockup-Server) but additionally implements dynamic functions like simulating reboots. The server runs once per client data set, i.e. BMC. -To simulate booting Servers to run the `metalprobe` tool, a custom `boot-operator`-like implementation runs the `metalprobe` agent once per discovered `ServerBootConfiguration` and reports back bogus data. This works fine for simple tests. - -### Vagrant environment -Manages a [vagrant](https://developer.hashicorp.com/vagrant)-based environment that provides a network setup as close to a physical environment as possible. Its primary focus is to provide a reference setup for a physical lab. It supports development for scripts, Ansible playbooks etc. that can be used to set up actual infrastructure. It does not support running tests against its nodes. **Its current state is a work in progress. It can probably be replaced by a containerlab-based setup.** - -## Predefined values -Two predefined value files that point to the DMTF- or Go-based mock exist for the `kind`-environment: -- `infra/kind/values-basic-go.yaml` -- `infra/kind/values-contoso-go.yaml` - -## Caveats -### Dependencies on forks -#### Metal-operator -The `kind`-environment depends on two services that currently live in a [fork of the metal-operator](https://github.com/simontesar/metal-operator): -* A Go implementation of a [redfish mock server](https://github.com/simontesar/metal-operator/blob/dell/bmc/mock/main.go) that is included in the upstream metal-operator for testing but modified in the fork to support some dynamic features like `lastResetTime` and replaceable client mock data to be able to test against mocks of specific BMC models. -* The `metalprobe-mock-controller` that watches `ServerBootConfigurations` for BMC mocks and runs a `metalprobe` agent for every instance. It simulates a server controlled by the BMC mock booting up and running `metalprobe` to report to the metal-operator's registry. The reason it lives in the fork is that the `probe`-package of the metal-operator is internal. diff --git a/infra/kind/Makefile b/infra/kind/Makefile deleted file mode 100644 index 574fca2..0000000 --- a/infra/kind/Makefile +++ /dev/null @@ -1,159 +0,0 @@ -SHELL=/usr/bin/env bash - -# Always use the kubeconfig next to this Makefile so kind and kubectl -# targets share a cluster-local config and do not touch ~/.kube/config. -export KUBECONFIG := $(CURDIR)/kubeconfig.yaml - -KUSTOMIZE ?= kustomize -KUBECTL ?= kubectl - -KIND_CLUSTER_NAME ?= metal -REDFISH_CLIENTS_DIR ?= ../../redfish-mockup-clients - -METAL_OPERATOR_DIR ?= ../../../metal-operator -METAL_OPERATOR_STACK ?= ../../config/metal-operator -CERT_MANAGER_VERSION ?= v1.17.1 -CERT_MANAGER_MANIFEST ?= https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml -CONTROLLER_IMG ?= controller:latest -METALDATA_IMG ?= metaldata:latest -BMC_MOCK_SERVER_IMG ?= mock-server:latest -IMG ?= metalprobe-mock-controller:latest -METALPROBE_MOCK_CONTROLLER_BIN ?= $(METAL_OPERATOR_DIR)/bin/metalprobe-mock-controller -METALPROBE_MOCK_CONTROLLER_STACK ?= ../../config/metalprobe-mock-controller - -MOCKUP_INSTANCES := r660 r770 r7725 xe9712 gpu-dpu basic -GO_MOCKUP_INSTANCES := r660 r770 r7725 xe9712 gpu-dpu basic contoso -REDFISH_MOCKUPS_STACK ?= ../../config/redfish-mockups/instances - -.PHONY: help deploy destroy \ - kind-create kind-delete \ - download-redfish-mockup-clients \ - cert-manager-install cert-manager-wait \ - metal-operator-images metal-operator-deploy metal-operator-delete \ - metal-operator-deploy-wait \ - bmc-mock-server-docker-build bmc-mock-server-kind-load \ - metalprobe-mock-controller-build metalprobe-mock-controller-run \ - metalprobe-mock-controller-docker-build metalprobe-mock-controller-kind-load \ - metalprobe-mock-controller-apply metalprobe-mock-controller-delete \ - dmtf-mock-apply-all dmtf-mock-delete-all \ - go-mock-apply-all go-mock-delete-all - -define mockup_instance_targets -.PHONY: dmtf-mock-apply-$(1) -dmtf-mock-apply-$(1): ## Apply the $(1) DMTF Redfish mockup overlay - $(KUSTOMIZE) build $(REDFISH_MOCKUPS_STACK)/$(1) | $(KUBECTL) apply -f - - -.PHONY: dmtf-mock-delete-$(1) -dmtf-mock-delete-$(1): ## Delete the $(1) DMTF Redfish mockup overlay - $(KUSTOMIZE) build $(REDFISH_MOCKUPS_STACK)/$(1) | $(KUBECTL) delete -f - -endef - -define go_mockup_instance_targets -.PHONY: go-mock-apply-$(1) -go-mock-apply-$(1): ## Apply the $(1) Go Redfish mockup overlay - $(KUSTOMIZE) build $(REDFISH_MOCKUPS_STACK)/$(1)-go | $(KUBECTL) apply -f - - -.PHONY: go-mock-delete-$(1) -go-mock-delete-$(1): ## Delete the $(1) Go Redfish mockup overlay - $(KUSTOMIZE) build $(REDFISH_MOCKUPS_STACK)/$(1)-go | $(KUBECTL) delete -f - -endef - -$(foreach inst,$(MOCKUP_INSTANCES),$(eval $(call mockup_instance_targets,$(inst)))) -$(foreach inst,$(GO_MOCKUP_INSTANCES),$(eval $(call go_mockup_instance_targets,$(inst)))) - -help: ## Show available targets - @grep -E '^[a-zA-Z0-9_.-]+:.*##' $(MAKEFILE_LIST) | \ - awk 'BEGIN {FS = ":.*## "}; {printf " %-24s %s\n", $$1, $$2}' - -download-redfish-mockup-clients: ## Download and extract Dell iDRAC Redfish mockup client data - ./scripts/download-redfish-mockup-clients.sh $(REDFISH_CLIENTS_DIR) - -kind-create: download-redfish-mockup-clients ## Create the local kind cluster - @kind get clusters 2>/dev/null | grep -qx "$(KIND_CLUSTER_NAME)" || \ - printf 'kind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnodes:\n- role: control-plane\n extraMounts:\n - hostPath: %s\n containerPath: /redfish-clients\n readOnly: true\n' "$(REDFISH_CLIENTS_DIR)" | \ - kind create cluster --name $(KIND_CLUSTER_NAME) --config=- - -kind-delete: ## Destroy the local kind cluster - kind delete cluster --name $(KIND_CLUSTER_NAME) - rm -f $(KUBECONFIG) - -cert-manager-install: ## Install cert-manager from upstream release manifest - $(KUBECTL) apply -f $(CERT_MANAGER_MANIFEST) - -cert-manager-wait: ## Wait for cert-manager deployments to become available - @until $(KUBECTL) get ns cert-manager >/dev/null 2>&1; do \ - echo "Waiting for cert-manager namespace..."; sleep 5; \ - done - $(KUBECTL) wait --for=condition=Available \ - deployment/cert-manager -n cert-manager --timeout=300s - $(KUBECTL) wait --for=condition=Available \ - deployment/cert-manager-webhook -n cert-manager --timeout=300s - $(KUBECTL) wait --for=condition=Available \ - deployment/cert-manager-cainjector -n cert-manager --timeout=300s - -metal-operator-images: ## Build and load controller/metaldata images into Kind - $(MAKE) -C $(METAL_OPERATOR_DIR) docker-build \ - CONTROLLER_IMG=$(CONTROLLER_IMG) METALDATA_IMG=$(METALDATA_IMG) - kind load docker-image $(CONTROLLER_IMG) $(METALDATA_IMG) \ - --name $(KIND_CLUSTER_NAME) - -metal-operator-deploy: ## Deploy metal-operator via kustomize overlay - $(MAKE) -C $(METAL_OPERATOR_DIR) manifests - $(KUSTOMIZE) build $(METAL_OPERATOR_STACK) | $(KUBECTL) apply -f - - -metal-operator-delete: ## Delete metal-operator kustomize overlay - $(KUSTOMIZE) build $(METAL_OPERATOR_STACK) | \ - $(KUBECTL) delete -f - --ignore-not-found - -metal-operator-deploy-wait: ## Install cert-manager and metal-operator, then wait -metal-operator-deploy-wait: cert-manager-install cert-manager-wait \ - metal-operator-images metal-operator-deploy - @until $(KUBECTL) get ns metal-operator-system >/dev/null 2>&1; do \ - echo "Waiting for metal-operator-system namespace..."; sleep 5; \ - done - @until $(KUBECTL) -n metal-operator-system \ - get deploy metal-operator-controller-manager >/dev/null 2>&1; do \ - echo "Waiting for metal-operator deployment..."; sleep 5; \ - done - $(KUBECTL) wait --for=condition=Available \ - deployment/metal-operator-controller-manager \ - -n metal-operator-system --timeout=600s - -deploy: kind-create metal-operator-deploy-wait \ - bmc-mock-server-kind-load \ - metalprobe-mock-controller-kind-load metalprobe-mock-controller-apply \ - dmtf-mock-apply-all go-mock-apply-all ## Create the kind cluster, deploy metal-operator, and stand up all mocks - -destroy: kind-delete ## Tear down the kind cluster - -bmc-mock-server-docker-build: ## Build bmc-mock-server container image - cd $(METAL_OPERATOR_DIR) && docker build --target mock-server -t $(BMC_MOCK_SERVER_IMG) . - -bmc-mock-server-kind-load: bmc-mock-server-docker-build ## Load bmc-mock-server image into Kind - kind load docker-image $(BMC_MOCK_SERVER_IMG) --name $(KIND_CLUSTER_NAME) - -metalprobe-mock-controller-build: ## Build metalprobe-mock-controller binary in metal-operator - cd $(METAL_OPERATOR_DIR) && go build -o bin/metalprobe-mock-controller ./cmd/metalprobe-mock-controller - -metalprobe-mock-controller-run: metalprobe-mock-controller-build ## Run metalprobe-mock-controller locally - $(METALPROBE_MOCK_CONTROLLER_BIN) --registry-url=http://localhost:30000 - -metalprobe-mock-controller-docker-build: ## Build metalprobe-mock-controller container image - cd $(METAL_OPERATOR_DIR) && docker build -f Dockerfile.metalprobe-mock-controller -t $(IMG) . - -metalprobe-mock-controller-kind-load: metalprobe-mock-controller-docker-build ## Load image into Kind cluster - kind load docker-image $(IMG) --name $(KIND_CLUSTER_NAME) - -metalprobe-mock-controller-apply: ## Apply metalprobe-mock-controller to the cluster - $(KUSTOMIZE) build $(METALPROBE_MOCK_CONTROLLER_STACK) | $(KUBECTL) apply -f - - -metalprobe-mock-controller-delete: ## Delete metalprobe-mock-controller from the cluster - $(KUSTOMIZE) build $(METALPROBE_MOCK_CONTROLLER_STACK) | $(KUBECTL) delete -f - - -dmtf-mock-apply-all: $(addprefix dmtf-mock-apply-,$(MOCKUP_INSTANCES)) ## Apply all registered DMTF mockup overlays - -dmtf-mock-delete-all: $(addprefix dmtf-mock-delete-,$(MOCKUP_INSTANCES)) ## Delete all registered DMTF mockup overlays - -go-mock-apply-all: $(addprefix go-mock-apply-,$(GO_MOCKUP_INSTANCES)) ## Apply all registered Go mockup overlays - -go-mock-delete-all: $(addprefix go-mock-delete-,$(GO_MOCKUP_INSTANCES)) ## Delete all registered Go mockup overlays diff --git a/infra/kind/README.md b/infra/kind/README.md deleted file mode 100644 index 7d78ac7..0000000 --- a/infra/kind/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# Kind environment -The kind-based setup runs the following services in the cluster itself: -* The metal-operator, including its BMC mock server with the embedded "contoso" data -* One instance of the python-based [DMTF Redfish Mockup server](https://github.com/DMTF/Redfish-Mockup-Server) for every set of Dell client data -* One instance of the modified metal-operator BMC mock server for every set of Dell client data -* The `metalprobe-mock-controller` that simulates booting for a theoretical server attached to every BMC mock server by watching for `ServerBootConfigurations` and starting a `metalprobe` agent for every instance to mimic a real server reporting back data to the metal-operator's registry - -By default one BMC resource for every Dell mock server instance is created in the cluster. - -## Usage -Deploy and inspect the complete setup: -``` -$ make deploy -… -$ export KUBECONFIG=$PWD/kubeconfig.yaml -$ kubectl get pods -A -NAMESPACE NAME READY STATUS RESTARTS AGE -cert-manager cert-manager-84b68949d9-8mwjj 1/1 Running 0 6m20s -cert-manager cert-manager-cainjector-77cb85f745-d48lt 1/1 Running 0 6m20s -cert-manager cert-manager-webhook-967c999c4-pvncs 1/1 Running 0 6m20s -kube-system coredns-589f44dc88-2nx6r 1/1 Running 0 6m20s -kube-system coredns-589f44dc88-grss8 1/1 Running 0 6m20s -kube-system etcd-metal-control-plane 1/1 Running 0 6m26s -kube-system kindnet-rcmnq 1/1 Running 0 6m20s -kube-system kube-apiserver-metal-control-plane 1/1 Running 0 6m27s -kube-system kube-controller-manager-metal-control-plane 1/1 Running 0 6m26s -kube-system kube-proxy-d6jzp 1/1 Running 0 6m20s -kube-system kube-scheduler-metal-control-plane 1/1 Running 0 6m27s -local-path-storage local-path-provisioner-855c7b7774-wfff7 1/1 Running 0 6m20s -metal-operator-system metal-operator-controller-manager-789b89587c-5j5bl 1/1 Running 0 4m7s -metal-operator-system metal-operator-metaldata-p48cb 1/1 Running 0 4m7s -metal-operator-system metalprobe-mock-controller-6f74c7bf58-dr2g4 1/1 Running 0 2m41s -metal-operator-system redfish-basic-go-mockup-784b67c45c-gbc6s 1/1 Running 0 2m39s -metal-operator-system redfish-basic-mockup-5c894b4cf8-9h675 1/1 Running 0 2m40s -metal-operator-system redfish-contoso-go-mockup-b94dd58-h9lm6 1/1 Running 0 2m38s -metal-operator-system redfish-gpu-dpu-go-mockup-dd99754c9-c78hh 1/1 Running 0 2m39s -metal-operator-system redfish-gpu-dpu-mockup-7b6fb4898b-p9mf2 1/1 Running 0 2m40s -metal-operator-system redfish-r660-go-mockup-64857469b7-9dsxj 1/1 Running 0 2m40s -metal-operator-system redfish-r660-mockup-555d84fb5d-xl49v 1/1 Running 0 2m41s -metal-operator-system redfish-r770-go-mockup-7bff6db8cc-l7vdv 1/1 Running 0 2m39s -metal-operator-system redfish-r770-mockup-74b987985b-7bps6 1/1 Running 0 2m41s -metal-operator-system redfish-r7725-go-mockup-687bf85694-d7bf6 1/1 Running 0 2m39s -metal-operator-system redfish-r7725-mockup-6c7f949c98-bhr4m 1/1 Running 0 2m40s -metal-operator-system redfish-xe9712-go-mockup-6d5849ddbf-8jg7k 1/1 Running 0 2m39s -metal-operator-system redfish-xe9712-mockup-966fb558d-zvp5k 1/1 Running 0 2m40s -$ kubectl get bmc -NAME MACADDRESS IP MODEL STATE POWERSTATE AGE -redfish-basic-go-mockup 10.96.200.25 15G Monolithic Enabled On 3m -redfish-basic-mockup 10.96.200.15 15G Monolithic Enabled On 3m1s -redfish-contoso-go-mockup 10.96.200.26 Joo Janta 200 Enabled On 2m59s -redfish-gpu-dpu-go-mockup 10.96.200.24 16G Monolithic Enabled On 3m -redfish-gpu-dpu-mockup 10.96.200.14 16G Monolithic Enabled On 3m1s -redfish-r660-go-mockup 10.96.200.20 16G Monolithic Enabled On 3m1s -redfish-r660-mockup 10.96.200.10 16G Monolithic Enabled On 3m2s -redfish-r770-go-mockup 10.96.200.21 17G Monolithic Enabled On 3m -redfish-r770-mockup 10.96.200.11 17G Monolithic Enabled On 3m2s -redfish-r7725-go-mockup 10.96.200.22 17G Monolithic Enabled On 3m -redfish-r7725-mockup 10.96.200.12 17G Monolithic Enabled On 3m1s -redfish-xe9712-go-mockup 10.96.200.23 17G Monolithic Enabled On 3m -redfish-xe9712-mockup 10.96.200.13 17G Monolithic Enabled On 3m1s -``` - -Run a test against the basic go instance: -```shell -$ cd ../.. -$ export KUBECONFIG=$PWD/kubeconfig.yaml -$ make test/03-power-annotation VALUES=infra/kind/values-basic-go.yaml CHAINSAW_EXTRA_FLAGS="--pause-on-failure" -``` - -Tear down: -```shell -$ cd - -$ make kind-delete -``` \ No newline at end of file diff --git a/infra/kind/scripts/download-redfish-mockup-clients.sh b/infra/kind/scripts/download-redfish-mockup-clients.sh deleted file mode 100755 index 9a27255..0000000 --- a/infra/kind/scripts/download-redfish-mockup-clients.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# Downloads and extracts Dell's iDRAC Redfish mockup client data -set -euo pipefail - -TARGET_DIR="${1:-../../redfish-mockup-clients}" - -REPO_RAW_BASE="https://raw.githubusercontent.com/dell/iDRAC-Redfish-Scripting/master/iDRAC%20Redfish%20Mockup%20Clients" - -CLIENTS=( - R660xs_iDRAC9_7_20_10_05_mockup_client - R770_iDRAC10_1_10_17_00_mockup_client - R7725_iDRAC10_1_20_70_50_mockup_client - XE9712_iDRAC10_1_30_07_10_mockup_client - iDRAC_mockup_client_GPU_DPU_config - iDRAC_mockup_client_basic_config -) - -command -v curl >/dev/null || { echo "curl is required" >&2; exit 1; } -command -v unzip >/dev/null || { echo "unzip is required" >&2; exit 1; } - -mkdir -p "${TARGET_DIR}" - -TMP_DIR="$(mktemp -d)" -trap 'rm -rf "${TMP_DIR}"' EXIT - -for client in "${CLIENTS[@]}"; do - if [[ -d "${TARGET_DIR}/${client}" ]]; then - echo "Skipping ${client} (already present in ${TARGET_DIR})" - continue - fi - - echo "Downloading ${client}.zip" - curl -fsSL -o "${TMP_DIR}/${client}.zip" "${REPO_RAW_BASE}/${client}.zip" - - echo "Extracting ${client}.zip into ${TARGET_DIR}" - unzip -q "${TMP_DIR}/${client}.zip" -d "${TARGET_DIR}" - rm -f "${TMP_DIR}/${client}.zip" -done - -echo "Redfish mockup clients ready in ${TARGET_DIR}" diff --git a/infra/kind/values-basic-go.yaml b/infra/kind/values-basic-go.yaml deleted file mode 100644 index 0e57169..0000000 --- a/infra/kind/values-basic-go.yaml +++ /dev/null @@ -1,9 +0,0 @@ -bmcIP: "10.96.200.25" -bmcPort: 8000 -bmcScheme: http -username: foo -password: bar -firmwareVersion: "7.10.30.00" -01-bmc-registration: - model: "15G Monolithic" - powerState: "On" diff --git a/infra/kind/values-contoso-go.yaml b/infra/kind/values-contoso-go.yaml deleted file mode 100644 index 329782a..0000000 --- a/infra/kind/values-contoso-go.yaml +++ /dev/null @@ -1,9 +0,0 @@ -bmcIP: "10.96.200.26" -bmcPort: 8000 -bmcScheme: http -username: foo -password: bar -firmwareVersion: "1.45.455b66-rev4" -01-bmc-registration: - model: "Joo Janta 200" - powerState: "On" diff --git a/infra/local/.env b/infra/local/.env deleted file mode 100644 index e969612..0000000 --- a/infra/local/.env +++ /dev/null @@ -1,12 +0,0 @@ -# Parent device for VLAN subinterfaces and master's trunk bridge. -PARENT_IF=dummy0 - -# Host VLAN interfaces created by setup-host-vlans.sh -VLAN100_BRIDGE=vlan0 -VLAN200_BRIDGE=vlan1 - -# Upstream networks for master's IB/OOB uplinks -UPSTREAM_IB_BRIDGE=dummy0 -UPSTREAM_OOB_BRIDGE=dummy0 - -TRUNK_BRIDGE=dummy0 diff --git a/infra/local/.envrc b/infra/local/.envrc deleted file mode 100644 index 72d0910..0000000 --- a/infra/local/.envrc +++ /dev/null @@ -1,3 +0,0 @@ -dotenv - -export KUBECONFIG=$PWD/kubeconfig diff --git a/infra/local/.gitignore b/infra/local/.gitignore deleted file mode 100644 index ee08860..0000000 --- a/infra/local/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -inventory - diff --git a/infra/local/Makefile b/infra/local/Makefile deleted file mode 100644 index 952a476..0000000 --- a/infra/local/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -KUBECONFIG ?= $(CURDIR)/kubeconfig -KUSTOMIZE ?= kustomize -KUBECTL ?= kubectl - -METAL_OPERATOR_DIR ?= ../../../metal-operator -METAL_OPERATOR_STACK ?= ../../config/metal-operator -CERT_MANAGER_VERSION ?= v1.17.1 -CERT_MANAGER_MANIFEST ?= https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml -CONTROLLER_IMG ?= controller:latest -METALDATA_IMG ?= metaldata:latest - -.PHONY: help host-vlans host-vlans-clean up-master up-workers up destroy clean \ - cert-manager-install cert-manager-wait \ - metal-operator-images metal-operator-deploy metal-operator-delete \ - metal-operator-deploy-wait - -help: ## Show available targets - @grep -E '^[a-zA-Z0-9_.-]+:.*##' $(MAKEFILE_LIST) | \ - awk 'BEGIN {FS = ":.*## "}; {printf " %-24s %s\n", $$1, $$2}' - -host-vlans: ## Create host VLAN interfaces - ./scripts/setup-host-vlans.sh create - -host-vlans-clean: ## Remove host VLAN interfaces - ./scripts/setup-host-vlans.sh cleanup - -up-master: ## Start master VM (network + k3s via host trigger) - vagrant up master - -up-workers: ## Start node1 and node2 VMs - vagrant up node1 node2 - -up: host-vlans up-master up-workers ## Bring up full lab environment - -destroy: ## Destroy all VMs - vagrant destroy -f - -clean: destroy host-vlans-clean ## Destroy VMs and remove host VLANs - -cert-manager-install: ## Install cert-manager from upstream release manifest - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) apply -f $(CERT_MANAGER_MANIFEST) - -cert-manager-wait: ## Wait for cert-manager deployments to become available - @until KUBECONFIG=$(KUBECONFIG) $(KUBECTL) get ns cert-manager >/dev/null 2>&1; do \ - echo "Waiting for cert-manager namespace..."; sleep 5; \ - done - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) wait --for=condition=Available \ - deployment/cert-manager -n cert-manager --timeout=300s - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) wait --for=condition=Available \ - deployment/cert-manager-webhook -n cert-manager --timeout=300s - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) wait --for=condition=Available \ - deployment/cert-manager-cainjector -n cert-manager --timeout=300s - -metal-operator-images: ## Build controller/metaldata images (import into k3s separately) - $(MAKE) -C $(METAL_OPERATOR_DIR) docker-build \ - CONTROLLER_IMG=$(CONTROLLER_IMG) METALDATA_IMG=$(METALDATA_IMG) - -metal-operator-deploy: ## Deploy metal-operator via kustomize overlay - $(MAKE) -C $(METAL_OPERATOR_DIR) manifests - KUBECONFIG=$(KUBECONFIG) $(KUSTOMIZE) build $(METAL_OPERATOR_STACK) | \ - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) apply -f - - -metal-operator-delete: ## Delete metal-operator kustomize overlay - KUBECONFIG=$(KUBECONFIG) $(KUSTOMIZE) build $(METAL_OPERATOR_STACK) | \ - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) delete -f - --ignore-not-found - -metal-operator-deploy-wait: ## Install cert-manager and metal-operator, then wait -metal-operator-deploy-wait: cert-manager-install cert-manager-wait \ - metal-operator-images metal-operator-deploy - @until KUBECONFIG=$(KUBECONFIG) $(KUBECTL) get ns metal-operator-system >/dev/null 2>&1; do \ - echo "Waiting for metal-operator-system namespace..."; sleep 5; \ - done - KUBECONFIG=$(KUBECONFIG) $(KUBECTL) wait --for=condition=Available \ - deployment/metal-operator-controller-manager \ - -n metal-operator-system --timeout=600s diff --git a/infra/local/README.md b/infra/local/README.md deleted file mode 100644 index 7eb8322..0000000 --- a/infra/local/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Local environment -The local `vagrant`-based environment's goal is to serve as a reference for a physical testing lab. It supports development for scripts, ansible playbooks etc. that can be used to setup actual infrastructure. It does not support running tests against its nodes. **Its current state is a work in progress. It can probably be replaced by a separate containerlab setup or by modifying the existing containerlab setup to use manual k8s installation.** - -It requires `libvirt`/`kvm`. - -## Usage -```shell -$ make up -… -``` - -## Network architecture - -![Network architecture](network-architecture.drawio.png) diff --git a/infra/local/Vagrantfile b/infra/local/Vagrantfile deleted file mode 100644 index fe17026..0000000 --- a/infra/local/Vagrantfile +++ /dev/null @@ -1,83 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : -# -# Boot order: provision master before workers so dnsmasq is ready for DHCP. -# vagrant up master && vagrant up node1 node2 - -parent_if = ENV.fetch("PARENT_IF", "dummy0") - -bridges = { - vlan100: ENV.fetch("VLAN100_BRIDGE", "vlan0"), - vlan200: ENV.fetch("VLAN200_BRIDGE", "vlan1"), - upstream_ib: ENV.fetch("UPSTREAM_IB_BRIDGE", parent_if), - upstream_oob: ENV.fetch("UPSTREAM_OOB_BRIDGE", parent_if), - trunk: ENV.fetch("TRUNK_BRIDGE", parent_if), -} - -Vagrant.configure("2") do |config| - config.vm.box = "bento/ubuntu-24.04" - - config.vm.define "master" do |master| - master.vm.hostname = "master" - master.vm.provider "libvirt" do |lv| - lv.memory = 4096 - lv.cpus = 2 - end - master.vm.network "public_network", - dev: bridges[:upstream_ib], - mode: "bridge", - auto_config: false - master.vm.network "public_network", - dev: bridges[:upstream_oob], - mode: "bridge", - auto_config: false - master.vm.network "public_network", - dev: bridges[:trunk], - mode: "bridge", - auto_config: false - master.vm.provision "shell", path: "scripts/provision-master.sh" - - master.trigger.after :up do |trigger| - trigger.name = "k3s" - trigger.run = { path: "scripts/provision-k3s.sh" } - end - end - - config.vm.define "node1" do |node1| - node1.vm.hostname = "node1" - node1.vm.provider "libvirt" do |lv| - lv.memory = 1024 - lv.cpus = 1 - end - node1.vm.network "public_network", - dev: bridges[:vlan100], - mode: "bridge", - mac: "02:00:64:00:01:01", - auto_config: false - node1.vm.network "public_network", - dev: bridges[:vlan200], - mode: "bridge", - mac: "02:00:c8:00:01:01", - auto_config: false - node1.vm.provision "shell", path: "scripts/provision-node.sh" - end - - config.vm.define "node2" do |node2| - node2.vm.hostname = "node2" - node2.vm.provider "libvirt" do |lv| - lv.memory = 1024 - lv.cpus = 1 - end - node2.vm.network "public_network", - dev: bridges[:vlan100], - mode: "bridge", - mac: "02:00:64:00:02:01", - auto_config: false - node2.vm.network "public_network", - dev: bridges[:vlan200], - mode: "bridge", - mac: "02:00:c8:00:02:01", - auto_config: false - node2.vm.provision "shell", path: "scripts/provision-node.sh" - end -end diff --git a/infra/local/group_vars/master.yaml b/infra/local/group_vars/master.yaml deleted file mode 100644 index 9e3f00c..0000000 --- a/infra/local/group_vars/master.yaml +++ /dev/null @@ -1,15 +0,0 @@ -dnsmasq_trunk_interface: eth3 - -dnsmasq_static_leases: - - mac: "02:00:64:00:01:01" - ip: 172.16.100.11 - hostname: node1-idrac - - mac: "02:00:c8:00:01:01" - ip: 10.250.200.11 - hostname: node1-nic1 - - mac: "02:00:64:00:02:01" - ip: 172.16.100.12 - hostname: node2-idrac - - mac: "02:00:c8:00:02:01" - ip: 10.250.200.12 - hostname: node2-nic1 diff --git a/infra/local/network-architecture.drawio.png b/infra/local/network-architecture.drawio.png deleted file mode 100644 index 473bc0fae3dbe18032dd715b554ad9c6c0c69647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45828 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 - exit 1 -fi - -cat > inventory <&2 - exit 1 -fi - -UPSTREAM_IB="${IFACES[1]}" -UPSTREAM_OOB="${IFACES[2]}" -TRUNK_IF="${IFACES[3]}" - -cat > /etc/netplan/60-master-network.yaml <&2 - exit 1 -fi - -IDRAC_IF="${IFACES[1]}" -NIC1_IF="${IFACES[2]}" - -cat > /etc/netplan/60-node-network.yaml </dev/null 2>&1; then - echo "Parent interface ${PARENT_IF} already exists, skipping create" - return 0 - fi - - if [[ "${PARENT_IF}" != dummy* ]]; then - echo "Parent interface ${PARENT_IF} not found and is not a dummy device (refusing to auto-create a real NIC)" >&2 - exit 1 - fi - - sudo ip link add "${PARENT_IF}" type dummy - sudo ip link set "${PARENT_IF}" up - echo "Created dummy parent ${PARENT_IF}" -} - -create_vlan() { - local iface="$1" - local vlan_id="$2" - local parent="$3" - - if ip link show "${iface}" >/dev/null 2>&1; then - echo "Interface ${iface} already exists, skipping create" - return 0 - fi - - sudo ip link add link "${parent}" name "${iface}" type vlan id "${vlan_id}" - sudo ip link set "${iface}" up - echo "Created ${iface} (VLAN ${vlan_id} on ${parent})" -} - -create_vlans() { - ensure_parent - create_vlan "${VLAN100_BRIDGE}" "${VLAN100_ID}" "${PARENT_IF}" - create_vlan "${VLAN200_BRIDGE}" "${VLAN200_ID}" "${PARENT_IF}" -} - -cleanup_host_interfaces() { - local destroyed=0 - local skipped=0 - - for iface in "${VLAN100_BRIDGE}" "${VLAN200_BRIDGE}"; do - if ip link show "${iface}" >/dev/null 2>&1; then - sudo ip link delete "${iface}" - echo "Destroyed ${iface}" - destroyed=$((destroyed + 1)) - else - echo "Skipped ${iface} (not present)" - skipped=$((skipped + 1)) - fi - done - - if [[ "${PARENT_IF}" == dummy* ]] && ip link show "${PARENT_IF}" >/dev/null 2>&1; then - sudo ip link delete "${PARENT_IF}" - echo "Destroyed dummy parent ${PARENT_IF}" - destroyed=$((destroyed + 1)) - fi - - echo "Cleanup complete: ${destroyed} destroyed, ${skipped} skipped" -} - -case "${1:-create}" in - create) - create_vlans - ;; - cleanup) - cleanup_host_interfaces - ;; - *) - echo "Usage: $0 [create|cleanup]" >&2 - exit 1 - ;; -esac diff --git a/infra/playbooks/group_vars/all.yml b/infra/playbooks/group_vars/all.yml deleted file mode 100644 index dd007aa..0000000 --- a/infra/playbooks/group_vars/all.yml +++ /dev/null @@ -1,2 +0,0 @@ -# Trunk NIC for VLAN subinterfaces; override per environment. -dnsmasq_trunk_interface: "" diff --git a/infra/playbooks/master.yaml b/infra/playbooks/master.yaml deleted file mode 100644 index ef637ca..0000000 --- a/infra/playbooks/master.yaml +++ /dev/null @@ -1,103 +0,0 @@ ---- -- name: Configure master node - hosts: master - become: true - vars: - k3s_bind_address: "0.0.0.0" - k3s_install_exec: >- - server --bind-address {{ k3s_bind_address }} - --tls-san {{ ansible_host }} - --write-kubeconfig-mode 644 - - tasks: - - name: Require dnsmasq trunk interface - ansible.builtin.assert: - that: - - dnsmasq_trunk_interface | length > 0 - fail_msg: >- - Set dnsmasq_trunk_interface in environment group_vars. - tags: dnsmasq - - - name: Install dnsmasq - ansible.builtin.apt: - name: dnsmasq - state: present - update_cache: true - tags: dnsmasq - - - name: Deploy dhcp.conf - ansible.builtin.template: - src: templates/dhcp.conf.j2 - dest: /etc/dnsmasq.d/dhcp.conf - mode: "0644" - notify: Restart dnsmasq - tags: dnsmasq - - - name: Enable and start dnsmasq - ansible.builtin.systemd: - name: dnsmasq - enabled: true - state: started - tags: dnsmasq - - - name: Install k3s dependencies - ansible.builtin.apt: - name: - - curl - - ca-certificates - state: present - update_cache: true - tags: k3s - - - name: Install k3s server - ansible.builtin.shell: curl -sfL https://get.k3s.io | sh - - environment: - INSTALL_K3S_EXEC: "{{ k3s_install_exec }}" - args: - creates: /usr/local/bin/k3s - executable: /bin/bash - tags: k3s - - - name: Enable and start k3s - ansible.builtin.systemd: - name: k3s - enabled: true - state: started - tags: k3s - - - name: Wait for k3s node to be Ready - ansible.builtin.command: k3s kubectl get nodes - register: k3s_nodes - until: k3s_nodes.stdout is search(' Ready ') - retries: 12 - delay: 10 - changed_when: false - tags: k3s - - - name: Allow non-root read of k3s kubeconfig - ansible.builtin.file: - path: /etc/rancher/k3s/k3s.yaml - mode: "0644" - tags: k3s - - - name: Fetch kubeconfig to host - ansible.builtin.fetch: - src: /etc/rancher/k3s/k3s.yaml - dest: "{{ kubeconfig_dest }}" - flat: true - tags: k3s - - - name: Rewrite server address for host access - ansible.builtin.replace: - path: "{{ kubeconfig_dest }}" - regexp: 'server: https://[^:]+:6443' - replace: "server: https://{{ ansible_host }}:6443" - delegate_to: localhost - become: false - tags: k3s - - handlers: - - name: Restart dnsmasq - ansible.builtin.systemd: - name: dnsmasq - state: restarted diff --git a/infra/playbooks/templates/dhcp.conf.j2 b/infra/playbooks/templates/dhcp.conf.j2 deleted file mode 100644 index a4f83ec..0000000 --- a/infra/playbooks/templates/dhcp.conf.j2 +++ /dev/null @@ -1,16 +0,0 @@ -# DHCP only; systemd-resolved owns port 53 on Ubuntu. -port=0 -interface={{ dnsmasq_trunk_interface }}.100 -interface={{ dnsmasq_trunk_interface }}.200 -bind-interfaces -except-interface=lo - -dhcp-range=set:oob,172.16.100.0,static -dhcp-range=set:ib,10.250.200.0,static - -{% for lease in dnsmasq_static_leases %} -dhcp-host={{ lease.mac }},{{ lease.ip }},{{ lease.hostname }},infinite -{% endfor %} - -dhcp-option=tag:oob,option:router,172.16.100.1 -dhcp-option=tag:ib,option:router,10.250.200.1 diff --git a/redfish-mockup-clients/.gitkeep b/redfish-mockup-clients/.gitkeep deleted file mode 100644 index e69de29..0000000