diff --git a/.github/workflows/podvm_mkosi.yaml b/.github/workflows/podvm_mkosi.yaml index a9e252dce2..725dffee00 100644 --- a/.github/workflows/podvm_mkosi.yaml +++ b/.github/workflows/podvm_mkosi.yaml @@ -153,11 +153,15 @@ jobs: if: ${{ inputs.debug == true }} working-directory: src/cloud-api-adaptor/podvm-mkosi run: make image-debug + env: + MKOSI_VERSION: ${{ env.MKOSI_VERSION }} - name: Build mkosi image if: ${{ inputs.debug == false }} working-directory: src/cloud-api-adaptor/podvm-mkosi run: make image + env: + MKOSI_VERSION: ${{ env.MKOSI_VERSION }} - name: Upload the qcow2 with oras id: publish_oras_qcow2 diff --git a/.github/workflows/podvm_mkosi_ubuntu.yaml b/.github/workflows/podvm_mkosi_ubuntu.yaml index d60df61869..57a70bb6b2 100644 --- a/.github/workflows/podvm_mkosi_ubuntu.yaml +++ b/.github/workflows/podvm_mkosi_ubuntu.yaml @@ -77,7 +77,7 @@ permissions: {} jobs: build-image: name: Build mkosi Ubuntu image for ${{ inputs.arch }} - runs-on: ${{ inputs.arch == 's390x' && 's390x' || 'ubuntu-24.04' }} + runs-on: ${{ inputs.arch == 's390x' && 's390x' || (inputs.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04') }} permissions: contents: read # Required if we want to run on a fork? packages: write # Required to publish the oras package to ghcr @@ -163,6 +163,7 @@ jobs: run: make image-debug env: PODVM_DISTRO: ubuntu + MKOSI_VERSION: ${{ env.MKOSI_VERSION }} - name: Build mkosi image if: ${{ inputs.debug == false }} @@ -170,6 +171,7 @@ jobs: run: make image env: PODVM_DISTRO: ubuntu + MKOSI_VERSION: ${{ env.MKOSI_VERSION }} - name: Upload the qcow2 with oras id: publish_oras_qcow2 diff --git a/.github/workflows/podvm_publish.yaml b/.github/workflows/podvm_publish.yaml index 372f80d753..afe224a0e8 100644 --- a/.github/workflows/podvm_publish.yaml +++ b/.github/workflows/podvm_publish.yaml @@ -102,6 +102,7 @@ jobs: packages: write # Required to publish the oras package to ghcr id-token: write # Required to publish the attestation provenance to ghcr attestations: write # Required to publish the attestation provenance to ghcr + artifact-metadata: write # Required by podvm_mkosi_ubuntu.yaml to write attestation metadata strategy: fail-fast: false matrix: diff --git a/.github/workflows/podvm_smoketest.yaml b/.github/workflows/podvm_smoketest.yaml index 15141b454b..4b58d8f243 100644 --- a/.github/workflows/podvm_smoketest.yaml +++ b/.github/workflows/podvm_smoketest.yaml @@ -97,8 +97,8 @@ jobs: working-directory: src/cloud-api-adaptor run: | { - echo "KATA_REF=$(yq -e '.oci.kata-agent-ctl.reference' versions.yaml)"; - echo "KATA_REG=$(yq -e '.oci.kata-agent-ctl.registry' versions.yaml)"; + echo "KATA_REF=$(yq -e '.oci.kata-containers.reference' versions.yaml)"; + echo "KATA_REG=$(yq -e '.oci.kata-containers.registry' versions.yaml)"; } >> "$GITHUB_ENV" - name: Install kata-agent-ctl diff --git a/.github/workflows/podvm_smoketest_ubuntu.yaml b/.github/workflows/podvm_smoketest_ubuntu.yaml index 362baab750..1b44d1b4a3 100644 --- a/.github/workflows/podvm_smoketest_ubuntu.yaml +++ b/.github/workflows/podvm_smoketest_ubuntu.yaml @@ -123,8 +123,8 @@ jobs: run: | { echo "ORAS_VERSION=$(./hack/versions.py -q tools.oras)"; - echo "KATA_AGENT_CTL_REF=$(./hack/versions.py -q oci.kata-agent-ctl.reference)"; - echo "KATA_AGENT_CTL_REG=$(./hack/versions.py -q oci.kata-agent-ctl.registry)"; + echo "KATA_REF=$(./hack/versions.py -q oci.kata-containers.reference)"; + echo "KATA_REG=$(./hack/versions.py -q oci.kata-containers.registry)"; } >> "$GITHUB_ENV" - uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2.0.0 @@ -133,7 +133,7 @@ jobs: - name: Install kata-agent-ctl run: | - oras pull "${KATA_AGENT_CTL_REG}/agent-ctl:${KATA_AGENT_CTL_REF}-x86_64" + oras pull "${KATA_REG}/agent-ctl:${KATA_REF}-x86_64" tar --zstd -xf kata-static-agent-ctl.tar.zst cp opt/kata/bin/kata-agent-ctl /usr/local/bin diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml index 43c9d33467..a65d1a1267 100644 --- a/.github/workflows/zizmor.yaml +++ b/.github/workflows/zizmor.yaml @@ -28,6 +28,6 @@ jobs: fetch-depth: 0 - name: Run zizmor - uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 + uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 with: persona: auditor diff --git a/src/cloud-api-adaptor/Dockerfile b/src/cloud-api-adaptor/Dockerfile index 46441062dc..1c7a170a28 100644 --- a/src/cloud-api-adaptor/Dockerfile +++ b/src/cloud-api-adaptor/Dockerfile @@ -1,9 +1,9 @@ ARG BUILD_TYPE=dev -# golang:1.25.11 (based on Debian 13 trixie) -ARG BUILDER_BASE=golang@sha256:f188e8c16ea47a8b22d2bdcf6d9bcd07b63ea7876c199749c07bf31e0ab33bad -# debian:trixie-slim (matches golang:1.25.11 base for library compatibility) +# golang:1.25.12 (based on Debian 13 trixie) +ARG BUILDER_BASE=golang@sha256:d7912cedddfa15b2900a8dfb7187df0af5ec2cb424a371139b5b352fd3e6b740 +# debian:trixie-slim (matches golang:1.25.12 base for library compatibility) # Multi-arch manifest list digest supporting amd64, arm64, ppc64le,, s390x -ARG BASE=debian@sha256:109e2c65005bf160609e4ba6acf7783752f8502ad218e298253428690b9eaa4b +ARG BASE=debian@sha256:28de0877c2189802884ccd20f15ee41c203573bd87bb6b883f5f46362d24c5c2 # This dockerfile uses Go cross-compilation to build the binary, # we build on the host platform ($BUILDPLATFORM) and then copy the diff --git a/src/cloud-api-adaptor/byom/e2e/kind_cluster.sh b/src/cloud-api-adaptor/byom/e2e/kind_cluster.sh new file mode 100755 index 0000000000..653428f49a --- /dev/null +++ b/src/cloud-api-adaptor/byom/e2e/kind_cluster.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# Ref: https://stackoverflow.com/questions/299728/how-do-you-use-newgrp-in-a-script-then-stay-in-that-group-when-the-script-exits +newgrp docker < Dockerfile < **EKS-Specific Implementation** +> +> This guide is designed for **Amazon EKS** clusters, which automatically inject IRSA environment variables (`AWS_WEB_IDENTITY_TOKEN_FILE`, `AWS_ROLE_ARN`) and mount service account tokens when you annotate a ServiceAccount. +> +> **For self-managed Kubernetes or other platforms:** +> - You must manually configure projected service account token volumes +> - Set `AWS_WEB_IDENTITY_TOKEN_FILE` and `AWS_ROLE_ARN` environment variables in the ConfigMap/Secret +> - Mount the OIDC token at the path specified in `AWS_WEB_IDENTITY_TOKEN_FILE` +> - See the [Alibaba Cloud RRSA implementation](https://github.com/confidential-containers/cloud-api-adaptor/blob/main/src/cloud-api-adaptor/install/charts/peerpods/templates/daemonset.yaml#L69-L128) in the Helm charts as a reference for manual OIDC token projection + +## Benefits + +- **No static credentials** - No long-lived AWS access keys in Kubernetes secrets +- **Automatic credential rotation** - Temporary credentials that auto-rotate +- **Fine-grained permissions** - Each service account can have different IAM roles +- **AWS best practice** - Follows AWS security recommendations for EKS workloads + +## Prerequisites + +- EKS cluster version 1.13 or later +- `kubectl` configured to access your cluster +- `aws` CLI version 2.0 or later +- `eksctl` +- Appropriate AWS IAM permissions to create roles and OIDC providers + +## Step 1: Enable OIDC Provider for Your EKS Cluster + +### Check if OIDC Issuer Exists + +```bash +# Set your cluster name +export CLUSTER_NAME="my-eks-cluster" +export AWS_REGION="us-east-2" + +# Get the OIDC issuer URL +aws eks describe-cluster \ + --name ${CLUSTER_NAME} \ + --region ${AWS_REGION} \ + --query "cluster.identity.oidc.issuer" \ + --output text +``` + +This should output something like: +``` +https://oidc.eks.us-east-2.amazonaws.com/id/31D259E489F3F8CDF111109DB7105368 +``` + +### Check if IAM OIDC Provider is Registered + +```bash +# Extract the OIDC ID +OIDC_ID=$(aws eks describe-cluster \ + --name ${CLUSTER_NAME} \ + --region ${AWS_REGION} \ + --query "cluster.identity.oidc.issuer" \ + --output text | awk -F'/' '{print $NF}') + +# Check if provider exists in IAM +aws iam list-open-id-connect-providers | grep ${OIDC_ID} +``` + +**If the command returns empty**, the OIDC provider is not registered in IAM and must be created. + +#### Create OIDC Provider (if needed) + +```bash +eksctl utils associate-iam-oidc-provider \ + --cluster ${CLUSTER_NAME} \ + --region ${AWS_REGION} \ + --approve + +# Verify the OIDC provider was created successfully +aws iam list-open-id-connect-providers | grep ${OIDC_ID} +``` + +### Get Account ID and OIDC Provider + +These values will be used for both cloud-api-adaptor and peerpod-ctrl: + +```bash +export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + +export OIDC_PROVIDER=$(aws eks describe-cluster \ + --name ${CLUSTER_NAME} \ + --region ${AWS_REGION} \ + --query "cluster.identity.oidc.issuer" \ + --output text | sed 's|https://||') + +echo "Account ID: ${ACCOUNT_ID}" +echo "OIDC Provider: ${OIDC_PROVIDER}" +``` + +## Step 2: Create IAM Role and Attach Permissions for cloud-api-adaptor + +### Define Variables + +```bash +export NAMESPACE="confidential-containers-system" +export CAA_SERVICE_ACCOUNT="cloud-api-adaptor" +export CAA_ROLE_NAME="CAA-IRSA-Role" +export CAA_POLICY_NAME="CAA-EC2-Policy" +``` + +### Create Trust Policy for cloud-api-adaptor + +```bash +cat > /tmp/caa-trust-policy.json < /tmp/caa-ec2-policy.json < /tmp/peerpod-ctrl-trust-policy.json < /tmp/peerpod-ctrl-ec2-policy.json < at release time +# Upstream dev image required for this provider (includes CGO bindings). +# The Cohere fork publishes release-only images, so keep this explicit override. image: - tag: "2d2e7c2c0736ec41c889cd98442a598b8b93bc0b-dev" + name: "quay.io/confidential-containers/cloud-api-adaptor" + tag: "f5dd0b2657a76482c6acabe0285cc87eb5d49473-dev" providerConfigs: docker: {} diff --git a/src/cloud-api-adaptor/install/charts/peerpods/providers/libvirt.yaml b/src/cloud-api-adaptor/install/charts/peerpods/providers/libvirt.yaml index 79b3b541f7..2ec83153aa 100644 --- a/src/cloud-api-adaptor/install/charts/peerpods/providers/libvirt.yaml +++ b/src/cloud-api-adaptor/install/charts/peerpods/providers/libvirt.yaml @@ -4,10 +4,11 @@ provider: libvirt -# Dev image required for this provider (includes CGO bindings) -# Update to dev- at release time +# Upstream dev image required for this provider (includes CGO bindings). +# The Cohere fork publishes release-only images, so keep this explicit override. image: - tag: "2d2e7c2c0736ec41c889cd98442a598b8b93bc0b-dev" + name: "quay.io/confidential-containers/cloud-api-adaptor" + tag: "f5dd0b2657a76482c6acabe0285cc87eb5d49473-dev" providerConfigs: libvirt: {} diff --git a/src/cloud-api-adaptor/install/charts/peerpods/templates/rbac-multi-provider.yaml b/src/cloud-api-adaptor/install/charts/peerpods/templates/rbac-multi-provider.yaml index 631fb85931..fe42455d5a 100644 --- a/src/cloud-api-adaptor/install/charts/peerpods/templates/rbac-multi-provider.yaml +++ b/src/cloud-api-adaptor/install/charts/peerpods/templates/rbac-multi-provider.yaml @@ -18,7 +18,7 @@ metadata: {{ include "peerpods.providerLabels" (dict "root" $ "provider" $provider) | nindent 4 }} rules: - apiGroups: [""] - resources: ["pods"] + resources: ["pods", "secrets", "serviceaccounts"] verbs: ["get", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 diff --git a/src/cloud-api-adaptor/install/charts/peerpods/tests/check-multi-provider.sh b/src/cloud-api-adaptor/install/charts/peerpods/tests/check-multi-provider.sh index ea8460f831..62f25ae31a 100755 --- a/src/cloud-api-adaptor/install/charts/peerpods/tests/check-multi-provider.sh +++ b/src/cloud-api-adaptor/install/charts/peerpods/tests/check-multi-provider.sh @@ -173,7 +173,7 @@ fi assert_contains "${MINIMAL_OUT}" 'PROXY_TIMEOUT: "30m"' assert_count "${MINIMAL_OUT}" 'name: peer-pods-secret-gcp' 2 assert_count "${MINIMAL_OUT}" 'name: peer-pods-secret-azure' 2 -assert_missing "${MINIMAL_OUT}" 'resources: \["pods", "secrets", "serviceaccounts"\]' +assert_count "${MINIMAL_OUT}" 'resources: \["pods", "secrets", "serviceaccounts"\]' 2 assert_missing "${MINIMAL_OUT}" 'name: cloud-api-adaptor-(gcp|azure)-pp-secrets' echo "Rendering provider-specific credentials..." diff --git a/src/cloud-api-adaptor/install/charts/peerpods/values.yaml b/src/cloud-api-adaptor/install/charts/peerpods/values.yaml index 56680fa241..8e27272963 100644 --- a/src/cloud-api-adaptor/install/charts/peerpods/values.yaml +++ b/src/cloud-api-adaptor/install/charts/peerpods/values.yaml @@ -115,10 +115,11 @@ allowedCloudConfigAnnotations: [] # those fields into the corresponding providers[] entry before enabling this # mode; validation rejects non-default legacy settings. # -# Provider CAA service accounts cannot read Kubernetes Secrets, preventing one -# compromised provider from reading another provider's credentials. Registry -# authentication through pod or ServiceAccount imagePullSecrets is therefore -# not supported in multi-provider mode. +# As in upstream single-provider mode, provider CAA service accounts can read +# Pods, ServiceAccounts, and Secrets cluster-wide. CAA needs this access to +# resolve imagePullSecrets for peer pods in dynamically created namespaces. +# Treat every CAA as a cluster-trusted component and prefer workload identity +# over Kubernetes Secrets for cloud provider credentials. # # With secrets.mode=create, providerSecrets. supplies credentials for # that provider's dedicated Secret. If is absent, the chart falls back diff --git a/src/cloud-api-adaptor/podvm-mkosi/Makefile b/src/cloud-api-adaptor/podvm-mkosi/Makefile index 791965af60..b359c826c0 100644 --- a/src/cloud-api-adaptor/podvm-mkosi/Makefile +++ b/src/cloud-api-adaptor/podvm-mkosi/Makefile @@ -104,10 +104,10 @@ image: insecure-builder rm -rf ./build @echo "Building image..." ifeq ($(SE_BOOT),true) - $(call run_mkosi_in_container,--profile production --image system) + $(call run_mkosi_in_container,--profile production) sudo -E ../hack/build-s390x-se-image.sh else ifeq ($(ARCH),s390x) - $(call run_mkosi_in_container,--profile production --image system) + $(call run_mkosi_in_container,--profile production) sudo -E ../hack/build-s390x-image.sh else mkdir -p build diff --git a/src/cloud-api-adaptor/podvm/hack/cross-build-extras.sh b/src/cloud-api-adaptor/podvm/hack/cross-build-extras.sh index f34f476c66..20ad7a29dd 100755 --- a/src/cloud-api-adaptor/podvm/hack/cross-build-extras.sh +++ b/src/cloud-api-adaptor/podvm/hack/cross-build-extras.sh @@ -6,8 +6,9 @@ # If ARCH is not set, exit [[ -z $ARCH ]] && exit 0 -# If ARCH is equal to HOST, exit -[[ $ARCH = $(uname -m) ]] && exit 0 +# If ARCH is equal to HOST, exit (no cross-compilation needed) +# Use replacement pattern to normalize arm64 to aarch64 for comparison +[[ "${ARCH/arm64/aarch64}" = "$(uname -m)" ]] && exit 0 # Only gnu is available for s390x and aarch64 libc=$([[ $ARCH =~ s390x || $ARCH =~ aarch64 ]] && echo "gnu" || echo "musl") @@ -17,7 +18,21 @@ rustup target add "$rustTarget" source /etc/os-release || source /usr/lib/os-release if [[ ${ID_LIKE:-} == *"debian"* ]]; then - apt install -y "qemu-system-$ARCH" + # Map architecture names to QEMU package names for Debian/Ubuntu + # Verified package names from: apt-cache search '^qemu-system-' + case "$ARCH" in + x86_64) + qemu_pkg="qemu-system-x86" + ;; + aarch64) + qemu_pkg="qemu-system-arm" + ;; + *) + # s390x and ppc64le match directly + qemu_pkg="qemu-system-$ARCH" + ;; + esac + apt install -y "$qemu_pkg" apt install -y "gcc-$ARCH-linux-$libc" elif [[ "${ID_LIKE:-}" =~ "fedora" ]] || [[ "${ID:-}" =~ "fedora" ]]; then dnf install -y "qemu-system-$ARCH" diff --git a/src/cloud-api-adaptor/podvm/hack/smoke_test.sh b/src/cloud-api-adaptor/podvm/hack/smoke_test.sh index 9f0e4126bb..a51e8d5793 100755 --- a/src/cloud-api-adaptor/podvm/hack/smoke_test.sh +++ b/src/cloud-api-adaptor/podvm/hack/smoke_test.sh @@ -162,8 +162,8 @@ if [ -z "$KATACTL" ]; then echo "::error:: kata-agent-ctl command not cached for $(uname -m), please compile it yourself and put into PATH or current dir." exit 1 fi - KATA_REF=$(yq -e '.oci.kata-agent-ctl.reference' ${SCRIPTDIR}/../../versions.yaml) - KATA_REG=$(yq -e '.oci.kata-agent-ctl.registry' ${SCRIPTDIR}/../../versions.yaml) + KATA_REF=$(yq -e '.oci.kata-containers.reference' ${SCRIPTDIR}/../../versions.yaml) + KATA_REG=$(yq -e '.oci.kata-containers.registry' ${SCRIPTDIR}/../../versions.yaml) echo "::debug:: Pulling kata-ctl from ${KATA_REG}/agent-ctl:${KATA_REF}-x86_64" oras pull "${KATA_REG}/agent-ctl:${KATA_REF}-x86_64" tar --ztsd -xvf kata-static-agent-ctl.tar.zst ./opt/kata/bin/kata-agent-ctl --transform='s/opt\/kata\/bin\/kata-agent-ctl/kata-agent-ctl/' diff --git a/src/cloud-api-adaptor/test/provisioner/byom/provision_byom.properties b/src/cloud-api-adaptor/test/provisioner/byom/provision_byom.properties index 9e6f485b67..b9651ef9f5 100644 --- a/src/cloud-api-adaptor/test/provisioner/byom/provision_byom.properties +++ b/src/cloud-api-adaptor/test/provisioner/byom/provision_byom.properties @@ -6,7 +6,6 @@ # Running with Docker DOCKER_HOST="unix:///var/run/docker.sock" DOCKER_NETWORK_NAME="kind" -DOCKER_API_VERSION="1.48" BYOM_PODVM_IMAGE="quay.io/confidential-containers/podvm-byom-e2e-image-amd64:latest" diff --git a/src/cloud-api-adaptor/test/provisioner/byom/provision_common.go b/src/cloud-api-adaptor/test/provisioner/byom/provision_common.go index 3e31bbe770..c9efdb7e0a 100644 --- a/src/cloud-api-adaptor/test/provisioner/byom/provision_common.go +++ b/src/cloud-api-adaptor/test/provisioner/byom/provision_common.go @@ -14,14 +14,12 @@ import ( "time" pv "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/test/provisioner" - "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/test/provisioner/docker" log "github.com/sirupsen/logrus" "sigs.k8s.io/e2e-framework/pkg/envconf" ) -// ByomProvisioner uses DockerProvisioner for BYOM-specific functionality +// ByomProvisioner implements BYOM e2e provisioning type ByomProvisioner struct { - *docker.DockerProvisioner provisionerCreatedVMs []string // Track VMs created by this provisioner instance } @@ -96,24 +94,12 @@ func NewByomProvisioner(properties map[string]string) (pv.CloudProvisioner, erro if err := initByomProperties(properties); err != nil { return nil, err } - dockerProps := map[string]string{ - "DOCKER_HOST": ByomProps.DockerHost, - "DOCKER_NETWORK_NAME": ByomProps.DockerNetworkName, - "BYOM_PODVM_IMAGE": ByomProps.ByomPodvmImage, - "CLUSTER_NAME": ByomProps.ClusterName, - "CONTAINER_RUNTIME": ByomProps.ContainerRuntime, - "CAA_IMAGE": ByomProps.CaaImage, - "CAA_IMAGE_TAG": ByomProps.CaaImageTag, - } - dockerProvisioner, err := docker.NewDockerProvisioner(dockerProps) - if err != nil { - return nil, err + if ByomProps.DockerHost != "" { + os.Setenv("DOCKER_HOST", ByomProps.DockerHost) } - return &ByomProvisioner{ - DockerProvisioner: dockerProvisioner.(*docker.DockerProvisioner), - }, nil + return &ByomProvisioner{}, nil } func (b *ByomProvisioner) CreateCluster(ctx context.Context, cfg *envconf.Config) error { @@ -125,10 +111,24 @@ func (b *ByomProvisioner) CreateCluster(ctx context.Context, cfg *envconf.Config log.Infof("Using BYOM kind config from: %s", kindConfigPath) os.Setenv("KIND_CONFIG_FILE", kindConfigPath) - if err := b.DockerProvisioner.CreateCluster(ctx, cfg); err != nil { + workingDir := filepath.Dir(kindConfigPath) + + if err := b.createKindCluster(workingDir); err != nil { + log.Errorf("Error creating Kind cluster: %v", err) return err } + home, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to get user home directory: %w", err) + } + cfg.WithKubeconfigFile(filepath.Join(home, ".kube/config")) + + if err := pv.AddNodeRoleWorkerLabel(context.Background(), ByomProps.ClusterName, cfg); err != nil { + + return fmt.Errorf("failed to label nodes: %w", err) + } + // Update containerd configuration to not discard unpacked layers log.Info("Configuring containerd on worker node to keep unpacked layers...") @@ -197,8 +197,23 @@ func (b *ByomProvisioner) CreatePodVMInstance(ctx context.Context, cfg *envconf. return nil } +func (b *ByomProvisioner) CreateVPC(ctx context.Context, cfg *envconf.Config) error { + // BYOM e2e provisioning relies on local docker/kind resources + return nil +} + func (b *ByomProvisioner) DeleteCluster(ctx context.Context, cfg *envconf.Config) error { - return b.DockerProvisioner.DeleteCluster(ctx, cfg) + kindConfigPath, err := filepath.Abs(ByomProps.KindConfigFile) + if err != nil { + return fmt.Errorf("error getting absolute path of kind config file: %w", err) + } + + return b.deleteKindCluster(filepath.Dir(kindConfigPath)) +} + +func (b *ByomProvisioner) DeleteVPC(ctx context.Context, cfg *envconf.Config) error { + // BYOM e2e provisioning relies on local docker/kind resources + return nil } func (b *ByomProvisioner) DeletePodVMInstance(ctx context.Context, cfg *envconf.Config) error { @@ -223,6 +238,12 @@ func (b *ByomProvisioner) DeletePodVMInstance(ctx context.Context, cfg *envconf. return nil } +func (b *ByomProvisioner) UploadPodvm(imagePath string, ctx context.Context, cfg *envconf.Config) error { + // For BYOM e2e, the podvm artifact is represented by the container image configured in + // BYOM_PODVM_IMAGE, so there is nothing to upload here. + return nil +} + func (b *ByomProvisioner) GetProperties(ctx context.Context, cfg *envconf.Config) map[string]string { return map[string]string{ "VM_POOL_IPS": ByomProps.VMPoolIPs, @@ -455,3 +476,38 @@ func (b *ByomProvisioner) destroyContainer(containerName string) error { log.Infof("Container %s destroyed successfully", containerName) return nil } + +func (b *ByomProvisioner) createKindCluster(workingDir string) error { + // Create kind cluster by executing the script on the node + cmd := exec.Command("/bin/bash", "-c", "./kind_cluster.sh create") + cmd.Dir = workingDir + cmd.Stdout = os.Stdout + // TODO: better handle stderr. Messages getting out of order. + cmd.Stderr = os.Stderr + cmd.Env = os.Environ() + // Set CLUSTER_NAME and CONTAINER_RUNTIME if available. Also unset KUBECONFIG so that the default path is used. + cmd.Env = append(cmd.Env, "CLUSTER_NAME="+ByomProps.ClusterName, "KUBECONFIG=", "CONTAINER_RUNTIME="+ByomProps.ContainerRuntime) + err := cmd.Run() + if err != nil { + log.Errorf("Error creating Kind cluster: %v", err) + return err + } + + return nil +} + +func (b *ByomProvisioner) deleteKindCluster(workingDir string) error { + // Delete kind cluster by executing the script on the node + cmd := exec.Command("/bin/bash", "-c", "./kind_cluster.sh delete") + cmd.Dir = workingDir + cmd.Stdout = os.Stdout + // TODO: better handle stderr. Messages getting out of order. + cmd.Stderr = os.Stderr + cmd.Env = append(os.Environ(), "CLUSTER_NAME="+ByomProps.ClusterName, "KUBECONFIG=", "CONTAINER_RUNTIME="+ByomProps.ContainerRuntime) + err := cmd.Run() + if err != nil { + log.Errorf("Error deleting Kind cluster: %v", err) + return err + } + return nil +} diff --git a/src/cloud-api-adaptor/versions.yaml b/src/cloud-api-adaptor/versions.yaml index a7b69cdf9c..09238156b8 100644 --- a/src/cloud-api-adaptor/versions.yaml +++ b/src/cloud-api-adaptor/versions.yaml @@ -30,7 +30,7 @@ tools: cert-manager: v1.15.3 bats: 1.10.0 iptables-wrapper: bfef9e5087a198b50a4124bb9ce9d2c7c99025dd - golang: 1.25.11 + golang: 1.25.12 kcli: 99.0.202507200957 mkosi: v26 protoc: 3.16.0 @@ -49,7 +49,7 @@ git: reference: v1.5.0 kbs: url: https://github.com/confidential-containers/trustee - reference: 22788122660d6e9be3e4bf52704282de5fcc0a2a + reference: d4e317620c4039c89779b725f74974d8f005da66 # PodVM CI: UKI extract + TDX measurement (needs `tdx --disk` for RTMR[1]). # Tracks alhassankhedr/cc-167-tdx-measurement-toolkit until that branch merges to main. cvm-measure: @@ -64,7 +64,7 @@ oci: tag: "3.9" kata-containers: registry: ghcr.io/kata-containers/cached-artefacts - reference: 8dccf4cf37aeea4b6c2caacf3e61510d6eef2f71 # v3.29.0 + reference: bef049d07e34d467b3a0910fdc65f30aa4647a0a # v3.31.0 + tagging fix # Cohere fork of guest-components. The fork's publish-artifacts workflow # publishes attestation-agent (incl. a tdx-snp-nvidia variant that bundles # TDX + SNP + Azure SNP-vTPM + NVIDIA GPU attesters and libnvat.so), @@ -74,7 +74,3 @@ oci: guest-components: registry: ghcr.io/cohere-ai/guest-components reference: e31a803b1a9f7c7de93ed18040ce7bd92e639ad5 - kata-agent-ctl: - registry: ghcr.io/kata-containers/cached-artefacts - reference: 3.29.0 - diff --git a/src/cloud-providers/Makefile b/src/cloud-providers/Makefile index 7d48c28cb1..4b5eb1bf3d 100644 --- a/src/cloud-providers/Makefile +++ b/src/cloud-providers/Makefile @@ -14,10 +14,11 @@ define gen-provider-values "provider: \(.provider)", \ "", \ (if .provider == "libvirt" or .provider == "docker" then \ - "# Dev image required for this provider (includes CGO bindings)", \ - "# Update to dev- at release time", \ + "# Upstream dev image required for this provider (includes CGO bindings).", \ + "# The Cohere fork publishes release-only images, so keep this explicit override.", \ "image:", \ - " tag: \"2d2e7c2c0736ec41c889cd98442a598b8b93bc0b-dev\"", \ + " name: \"quay.io/confidential-containers/cloud-api-adaptor\"", \ + " tag: \"f5dd0b2657a76482c6acabe0285cc87eb5d49473-dev\"", \ "" \ else \ empty \ diff --git a/src/cloud-providers/aws/ec2.go b/src/cloud-providers/aws/ec2.go index ea1f7913ee..8c13242f56 100644 --- a/src/cloud-providers/aws/ec2.go +++ b/src/cloud-providers/aws/ec2.go @@ -13,28 +13,31 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2" ) -// TODO: Use IAM role func NewEC2Client(cloudCfg Config) (*ec2.Client, error) { var cfg aws.Config var err error if cloudCfg.AccessKeyID != "" && cloudCfg.SecretKey != "" { + logger.Printf("using static credentials") cfg, err = config.LoadDefaultConfig(context.TODO(), - config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(cloudCfg.AccessKeyID, cloudCfg.SecretKey, cloudCfg.SessionToken)), config.WithRegion(cloudCfg.Region)) - if err != nil { - return nil, fmt.Errorf("configuration error when using creds: %s", err) - } - - } else { - + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(cloudCfg.AccessKeyID, cloudCfg.SecretKey, cloudCfg.SessionToken)), + config.WithRegion(cloudCfg.Region)) + } else if cloudCfg.LoginProfile != "" { + logger.Printf("using shared profile: %s", cloudCfg.LoginProfile) cfg, err = config.LoadDefaultConfig(context.TODO(), config.WithRegion(cloudCfg.Region), config.WithSharedConfigProfile(cloudCfg.LoginProfile)) - if err != nil { - return nil, fmt.Errorf("configuration error when using shared profile: %s", err) - } + } else { + logger.Printf("using default credential chain (supports IRSA)") + cfg, err = config.LoadDefaultConfig(context.TODO(), + config.WithRegion(cloudCfg.Region)) + } + + if err != nil { + return nil, fmt.Errorf("failed to load AWS configuration: %w", err) } + client := ec2.NewFromConfig(cfg) return client, nil } diff --git a/src/cloud-providers/aws/ec2_test.go b/src/cloud-providers/aws/ec2_test.go new file mode 100644 index 0000000000..a0f672e4bd --- /dev/null +++ b/src/cloud-providers/aws/ec2_test.go @@ -0,0 +1,85 @@ +// (C) Copyright Confidential Containers Contributors +// SPDX-License-Identifier: Apache-2.0 + +package aws + +import ( + "os" + "testing" +) + +// TestNewEC2Client_StaticCredentials verifies that NewEC2Client uses static credentials when provided +func TestNewEC2Client_StaticCredentials(t *testing.T) { + // Clear any environment variables that might interfere + os.Unsetenv("AWS_WEB_IDENTITY_TOKEN_FILE") + os.Unsetenv("AWS_ROLE_ARN") + os.Unsetenv("AWS_ACCESS_KEY_ID") + os.Unsetenv("AWS_SECRET_ACCESS_KEY") + + cfg := Config{ + AccessKeyID: "AKIAIOSFODNN7EXAMPLE", + SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + Region: "us-east-1", + } + + // This should not panic or return error for invalid credentials (just test config creation) + // We can't actually test AWS connectivity without real credentials + client, err := NewEC2Client(cfg) + if err != nil { + t.Errorf("NewEC2Client with static credentials failed: %v", err) + } + if client == nil { + t.Error("Expected non-nil client") + } +} + +// TestNewEC2Client_DefaultCredentialChain verifies that NewEC2Client uses default credential chain when no static credentials +func TestNewEC2Client_DefaultCredentialChain(t *testing.T) { + // Clear any environment variables + os.Unsetenv("AWS_WEB_IDENTITY_TOKEN_FILE") + os.Unsetenv("AWS_ROLE_ARN") + os.Unsetenv("AWS_ACCESS_KEY_ID") + os.Unsetenv("AWS_SECRET_ACCESS_KEY") + + cfg := Config{ + AccessKeyID: "", + SecretKey: "", + Region: "us-east-1", + } + + // This should use default credential chain + // It will fail to find credentials in test environment, but the SDK initialization should work + client, err := NewEC2Client(cfg) + if err != nil { + t.Errorf("NewEC2Client with default credential chain failed: %v", err) + } + if client == nil { + t.Error("Expected non-nil client") + } +} + +// TestNewEC2Client_MissingSecretKey verifies that having only AccessKeyID without SecretKey still works +// (it will be ignored and fall through to default credential chain) +func TestNewEC2Client_PartialStaticCredentials(t *testing.T) { + // Clear environment + os.Unsetenv("AWS_WEB_IDENTITY_TOKEN_FILE") + os.Unsetenv("AWS_ROLE_ARN") + os.Unsetenv("AWS_ACCESS_KEY_ID") + os.Unsetenv("AWS_SECRET_ACCESS_KEY") + + // Only AccessKeyID, no SecretKey + cfg := Config{ + AccessKeyID: "AKIAIOSFODNN7EXAMPLE", + SecretKey: "", // Missing + Region: "us-east-1", + } + + // Should fall through to default credential chain since both are required for static credentials + client, err := NewEC2Client(cfg) + if err != nil { + t.Errorf("NewEC2Client with partial credentials failed: %v", err) + } + if client == nil { + t.Error("Expected non-nil client") + } +} diff --git a/src/cloud-providers/go.mod b/src/cloud-providers/go.mod index 9b0c5c349a..3543801171 100644 --- a/src/cloud-providers/go.mod +++ b/src/cloud-providers/go.mod @@ -1,6 +1,6 @@ module github.com/confidential-containers/cloud-api-adaptor/src/cloud-providers -go 1.25.11 +go 1.25.12 require ( cloud.google.com/go/compute v1.61.0 @@ -61,7 +61,6 @@ require ( github.com/moby/sys/atomicwriter v0.1.0 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect github.com/x448/float16 v0.8.4 // indirect - go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/oauth2 v0.36.0 // indirect @@ -145,15 +144,15 @@ require ( go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect golang.org/x/net v0.55.0 // indirect - golang.org/x/sync v0.20.0 // indirect + golang.org/x/sync v0.21.0 // indirect golang.org/x/sys v0.45.0 // indirect golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect + golang.org/x/text v0.39.0 // indirect golang.org/x/time v0.15.0 // indirect google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/grpc v1.80.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/grpc v1.82.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/src/cloud-providers/go.sum b/src/cloud-providers/go.sum index b96434c513..f606b35b2d 100644 --- a/src/cloud-providers/go.sum +++ b/src/cloud-providers/go.sum @@ -147,8 +147,8 @@ github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyM github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -171,11 +171,11 @@ github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= -github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= -github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= -github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -431,8 +431,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -470,8 +470,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -523,8 +523,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= +golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -539,8 +539,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -554,16 +554,16 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0= google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE= +google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/src/cloud-providers/libvirt/cloudinit_test.go b/src/cloud-providers/libvirt/cloudinit_test.go index 7153e90cf1..d4b628932a 100644 --- a/src/cloud-providers/libvirt/cloudinit_test.go +++ b/src/cloud-providers/libvirt/cloudinit_test.go @@ -5,7 +5,6 @@ package libvirt import ( CR "crypto/rand" - "fmt" "io" "math/rand" "os" @@ -19,48 +18,35 @@ import ( ) func TestCloudInit(t *testing.T) { + tests := []struct { + name string + userDataContent []byte + metaDataContent []byte + expectedFiles map[string][]byte + }{ + { + name: "basic cloud-init", + userDataContent: []byte("userdata"), + metaDataContent: []byte("metadata"), + expectedFiles: map[string][]byte{ + userDataFilename: []byte("userdata"), + metaDataFilename: []byte("metadata"), + }, + }, + } - file, err := os.CreateTemp("", "CloudInit-*.iso") - require.NoError(t, err) - defer os.Remove(file.Name()) - - fmt.Printf("temp file: %s", file.Name()) - - userDataContent := []byte("userdata") - metaDataContent := []byte("metadata") - - isoData, err := createCloudInit(userDataContent, metaDataContent) - require.NoError(t, err) - - err = os.WriteFile(file.Name(), isoData, os.ModePerm) - require.NoError(t, err) - - isoFile, err := os.Open(file.Name()) - require.NoError(t, err) - - isoImg, err := iso9660.OpenImage(isoFile) - require.NoError(t, err) - - rootFile, err := isoImg.RootDir() - require.NoError(t, err) - - children, err := rootFile.GetChildren() - require.NoError(t, err) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + isoData, err := createCloudInit(tt.userDataContent, tt.metaDataContent) + require.NoError(t, err) - files := make(map[string][]byte) - for _, child := range children { - key := child.Name() - data, err := io.ReadAll(child.Reader()) - require.NoError(t, err) + files := verifyISOContents(t, isoData) - files[key] = data + for filename, expectedContent := range tt.expectedFiles { + assert.Equal(t, expectedContent, files[filename]) + } + }) } - - assert.Equal(t, userDataContent, files[userDataFilename]) - assert.Equal(t, metaDataContent, files[metaDataFilename]) - - err = isoFile.Close() - require.NoError(t, err) } func TestInMemoryCopier(t *testing.T) { @@ -87,3 +73,106 @@ func TestInMemoryCopier(t *testing.T) { assert.Equal(t, buf, otherBuf) } + +func TestCreateCloudInitVariations(t *testing.T) { + largeData := make([]byte, 10000) + for i := range largeData { + largeData[i] = byte('A' + (i % 26)) + } + + tests := []struct { + name string + userDataContent []byte + metaDataContent []byte + expectError bool + verifyFileCount bool + expectedFileCount int + verifyVendorData bool + }{ + { + name: "empty data", + userDataContent: []byte(""), + metaDataContent: []byte(""), + expectError: false, + }, + { + name: "large data", + userDataContent: largeData, + metaDataContent: []byte("instance-id: test-instance\nlocal-hostname: test-host"), + expectError: false, + }, + { + name: "special characters", + userDataContent: []byte("#cloud-config\nusers:\n - name: test\n ssh-authorized-keys:\n - ssh-rsa AAAAB3..."), + metaDataContent: []byte("instance-id: test-123\nlocal-hostname: test-host-456"), + expectError: false, + verifyFileCount: true, + expectedFileCount: 3, + }, + { + name: "verify vendor data", + userDataContent: []byte("userdata"), + metaDataContent: []byte("metadata"), + expectError: false, + verifyVendorData: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + isoData, err := createCloudInit(tt.userDataContent, tt.metaDataContent) + + if tt.expectError { + assert.Error(t, err) + return + } + + require.NoError(t, err) + assert.NotEmpty(t, isoData) + + files := verifyISOContents(t, isoData) + + if tt.verifyFileCount { + assert.Equal(t, tt.expectedFileCount, len(files)) + } + + if tt.verifyVendorData { + assert.Contains(t, files, vendorDataFilename) + assert.Equal(t, []byte{}, files[vendorDataFilename]) + } + }) + } +} + +func verifyISOContents(t *testing.T, isoData []byte) map[string][]byte { + t.Helper() + + file, err := os.CreateTemp("", "CloudInit-*.iso") + require.NoError(t, err) + defer os.Remove(file.Name()) + + err = os.WriteFile(file.Name(), isoData, os.ModePerm) + require.NoError(t, err) + + isoFile, err := os.Open(file.Name()) + require.NoError(t, err) + defer isoFile.Close() + + isoImg, err := iso9660.OpenImage(isoFile) + require.NoError(t, err) + + rootFile, err := isoImg.RootDir() + require.NoError(t, err) + + children, err := rootFile.GetChildren() + require.NoError(t, err) + + files := make(map[string][]byte) + for _, child := range children { + data, err := io.ReadAll(child.Reader()) + require.NoError(t, err) + files[child.Name()] = data + } + + return files +} diff --git a/src/cloud-providers/libvirt/libvirt_test.go b/src/cloud-providers/libvirt/libvirt_test.go index 3c35f0e56e..7cbbcf6446 100644 --- a/src/cloud-providers/libvirt/libvirt_test.go +++ b/src/cloud-providers/libvirt/libvirt_test.go @@ -9,9 +9,18 @@ import ( provider "github.com/confidential-containers/cloud-api-adaptor/src/cloud-providers" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + libvirt "libvirt.org/go/libvirt" libvirtxml "libvirt.org/go/libvirtxml" ) +const ( + testBootDisk = "/var/lib/libvirt/images/root.qcow2" + testCiDataISO = "/var/lib/libvirt/images/cidata.iso" + testCloudInitISO = "/var/lib/libvirt/images/cloudinit.iso" + testNetworkName = "default" +) + var testCfg Config func init() { @@ -31,28 +40,22 @@ func TestLibvirtConnection(t *testing.T) { checkConfig(t) client, err := NewLibvirtClient(testCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer client.connection.Close() - assert.NotNil(t, client.nodeInfo) - assert.NotNil(t, client.caps) + assert.NotEmpty(t, client.nodeInfo) + assert.NotEmpty(t, client.caps) } func TestGetArchitecture(t *testing.T) { checkConfig(t) client, err := NewLibvirtClient(testCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer client.connection.Close() node, err := client.connection.GetNodeInfo() - if err != nil { - t.Error(err) - } + require.NoError(t, err) arch := node.Model if arch == "" { @@ -80,76 +83,75 @@ func verifyDomainXML(domXML *libvirtxml.Domain) error { return nil } -func TestCreateDomainXMLs390x(t *testing.T) { - checkConfig(t) - - client, err := NewLibvirtClient(testCfg) - if err != nil { - t.Error(err) - } - defer client.connection.Close() - - vm := vmConfig{} - - domainCfg := domainConfig{ - name: "TestCreateDomainS390x", - cpu: 2, - mem: 2, - networkName: client.networkName, - bootDisk: "/var/lib/libvirt/images/root.qcow2", - cidataDisk: "/var/lib/libvirt/images/cidata.iso", - } - - domCfg, err := createDomainXML(client, &domainCfg, &vm) - if err != nil { - t.Error(err) - } - - arch := domCfg.OS.Type.Arch - if domCfg.OS.Type.Arch != archS390x { - t.Skipf("Skipping because architecture is [%s] and not [%s].", arch, archS390x) - } - - // verify the config - err = verifyDomainXML(domCfg) - if err != nil { - t.Error(err) +func createTestDomainConfig(name string, cpu, mem uint, networkName, cidataDisk string) *domainConfig { + return &domainConfig{ + name: name, + cpu: cpu, + mem: mem, + networkName: networkName, + bootDisk: testBootDisk, + cidataDisk: cidataDisk, } } -func TestCreateDomainXMLaarch64(t *testing.T) { +func TestCreateDomainXMLArchitectures(t *testing.T) { checkConfig(t) client, err := NewLibvirtClient(testCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer client.connection.Close() - vm := vmConfig{} - - domainCfg := domainConfig{ - name: "TestCreateDomainAArch64", - cpu: 2, - mem: 4, - networkName: client.networkName, - bootDisk: "/var/lib/libvirt/images/root.qcow2", - cidataDisk: "/var/lib/libvirt/images/cloudinit.iso", + tests := []struct { + name string + domainName string + cpu uint + mem uint + cidataDisk string + expectedArch string + }{ + { + name: "s390x architecture", + domainName: "TestCreateDomainS390x", + cpu: 2, + mem: 2, + cidataDisk: testCiDataISO, + expectedArch: archS390x, + }, + { + name: "aarch64 architecture", + domainName: "TestCreateDomainAArch64", + cpu: 2, + mem: 4, + cidataDisk: testCloudInitISO, + expectedArch: archAArch64, + }, } - domCfg, err := createDomainXML(client, &domainCfg, &vm) - if err != nil { - t.Error(err) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + vm := vmConfig{} - arch := domCfg.OS.Type.Arch - if domCfg.OS.Type.Arch != archAArch64 { - t.Skipf("Skipping because architecture is [%s] and not [%s].", arch, archAArch64) - } + domainCfg := domainConfig{ + name: tt.domainName, + cpu: tt.cpu, + mem: tt.mem, + networkName: client.networkName, + bootDisk: testBootDisk, + cidataDisk: tt.cidataDisk, + } - err = verifyDomainXML(domCfg) - if err != nil { - t.Error(err) + domCfg, err := createDomainXML(client, &domainCfg, &vm) + assert.NoError(t, err) + + arch := domCfg.OS.Type.Arch + if domCfg.OS.Type.Arch != tt.expectedArch { + t.Skipf("Skipping because architecture is [%s] and not [%s].", arch, tt.expectedArch) + } + + // verify the config + err = verifyDomainXML(domCfg) + assert.NoError(t, err) + }) } } @@ -160,18 +162,36 @@ func TestGetDeletableDiskPaths(t *testing.T) { expected []string }{ { - name: "returns file-backed disks only", + name: "extract file-backed disks only", domain: &libvirtxml.Domain{ Devices: &libvirtxml.DomainDeviceList{ Disks: []libvirtxml.DomainDisk{ { Source: &libvirtxml.DomainDiskSource{ - File: &libvirtxml.DomainDiskSourceFile{File: "/var/lib/libvirt/images/root.qcow2"}, + File: &libvirtxml.DomainDiskSourceFile{File: testBootDisk}, }, }, { Source: &libvirtxml.DomainDiskSource{ - File: &libvirtxml.DomainDiskSourceFile{File: "/var/lib/libvirt/images/cloudinit.iso"}, + File: &libvirtxml.DomainDiskSourceFile{File: testCloudInitISO}, + }, + }, + }, + }, + }, + expected: []string{ + testBootDisk, + testCloudInitISO, + }, + }, + { + name: "skip disks without file source", + domain: &libvirtxml.Domain{ + Devices: &libvirtxml.DomainDeviceList{ + Disks: []libvirtxml.DomainDisk{ + { + Source: &libvirtxml.DomainDiskSource{ + File: &libvirtxml.DomainDiskSourceFile{File: testBootDisk}, }, }, { @@ -182,8 +202,7 @@ func TestGetDeletableDiskPaths(t *testing.T) { }, }, expected: []string{ - "/var/lib/libvirt/images/root.qcow2", - "/var/lib/libvirt/images/cloudinit.iso", + testBootDisk, }, }, { @@ -194,16 +213,299 @@ func TestGetDeletableDiskPaths(t *testing.T) { { name: "empty disk list returns empty slice", domain: &libvirtxml.Domain{ - Devices: &libvirtxml.DomainDeviceList{}, + Devices: &libvirtxml.DomainDeviceList{ + Disks: []libvirtxml.DomainDisk{}, + }, + }, + expected: []string{}, + }, + { + name: "skip disks with empty file path", + domain: &libvirtxml.Domain{ + Devices: &libvirtxml.DomainDeviceList{ + Disks: []libvirtxml.DomainDisk{ + { + Source: &libvirtxml.DomainDiskSource{ + File: &libvirtxml.DomainDiskSourceFile{File: ""}, + }, + }, + }, + }, }, expected: []string{}, }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - paths := getDeletableDiskPaths(tc.domain) - assert.Equal(t, tc.expected, paths) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + paths := getDeletableDiskPaths(tt.domain) + assert.Equal(t, tt.expected, paths) + }) + } +} + +func TestGetGuestForArchType(t *testing.T) { + tests := []struct { + name string + caps *libvirtxml.Caps + arch string + ostype string + expectError bool + expectArch string + }{ + { + name: "find x86_64 guest", + caps: createMockCaps("x86_64", ""), + arch: "x86_64", + ostype: "hvm", + expectError: false, + expectArch: "x86_64", + }, + { + name: "find s390x guest", + caps: createMockCaps("s390x", ""), + arch: "s390x", + ostype: "hvm", + expectError: false, + expectArch: "s390x", + }, + { + name: "find aarch64 guest", + caps: createMockCaps("aarch64", ""), + arch: "aarch64", + ostype: "hvm", + expectError: false, + expectArch: "aarch64", + }, + { + name: "architecture not found", + caps: createMockCaps("x86_64", ""), + arch: "invalid-arch", + ostype: "hvm", + expectError: true, + }, + { + name: "ostype mismatch", + caps: &libvirtxml.Caps{ + Guests: []libvirtxml.CapsGuest{ + { + OSType: "xen", + Arch: libvirtxml.CapsGuestArch{ + Name: "x86_64", + }, + }, + }, + }, + arch: "x86_64", + ostype: "hvm", + expectError: true, + }, + { + name: "empty capabilities", + caps: &libvirtxml.Caps{ + Guests: []libvirtxml.CapsGuest{}, + }, + arch: "x86_64", + ostype: "hvm", + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + guest, err := getGuestForArchType(tt.caps, tt.arch, tt.ostype) + if tt.expectError { + assert.Error(t, err) + assert.Nil(t, guest) + assert.ErrorContains(t, err, "could not find any guests") + } else { + assert.NoError(t, err) + require.NotNil(t, guest) + assert.Equal(t, tt.expectArch, guest.Arch.Name) + assert.Equal(t, tt.ostype, guest.OSType) + } + }) + } +} + +func TestLookupMachine(t *testing.T) { + tests := []struct { + name string + machines []libvirtxml.CapsGuestMachine + targetMachine string + expectedResult string + }{ + { + name: "find machine with canonical name", + machines: []libvirtxml.CapsGuestMachine{ + {Name: "pc", Canonical: "pc-i440fx-2.12"}, + {Name: "q35", Canonical: "pc-q35-2.12"}, + }, + targetMachine: "pc", + expectedResult: "pc-i440fx-2.12", + }, + { + name: "find machine without canonical name", + machines: []libvirtxml.CapsGuestMachine{ + {Name: "virt"}, + {Name: "pc"}, + }, + targetMachine: "virt", + expectedResult: "virt", + }, + { + name: "machine not found returns empty string", + machines: []libvirtxml.CapsGuestMachine{ + {Name: "pc"}, + {Name: "q35"}, + }, + targetMachine: "nonexistent", + expectedResult: "", + }, + { + name: "s390x machine with canonical", + machines: []libvirtxml.CapsGuestMachine{ + {Name: "s390-ccw-virtio", Canonical: "s390-ccw-virtio-rhel9.0.0"}, + }, + targetMachine: "s390-ccw-virtio", + expectedResult: "s390-ccw-virtio-rhel9.0.0", + }, + { + name: "empty machine list", + machines: []libvirtxml.CapsGuestMachine{}, + targetMachine: "pc", + expectedResult: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := lookupMachine(tt.machines, tt.targetMachine) + assert.Equal(t, tt.expectedResult, result) + }) + } +} + +func TestGetCanonicalMachineName(t *testing.T) { + tests := []struct { + name string + caps *libvirtxml.Caps + arch string + virttype string + targetMachine string + expectedResult string + expectError bool + }{ + { + name: "find canonical machine in arch machines", + caps: createMockCaps("x86_64", "", + libvirtxml.CapsGuestMachine{Name: "pc", Canonical: "pc-i440fx-2.12"}), + arch: "x86_64", + virttype: "hvm", + targetMachine: "pc", + expectedResult: "pc-i440fx-2.12", + expectError: false, + }, + { + name: "find canonical machine in domain machines", + caps: &libvirtxml.Caps{ + Guests: []libvirtxml.CapsGuest{ + { + OSType: "hvm", + Arch: libvirtxml.CapsGuestArch{ + Name: "x86_64", + Domains: []libvirtxml.CapsGuestDomain{ + { + Machines: []libvirtxml.CapsGuestMachine{ + {Name: "q35", Canonical: "pc-q35-2.12"}, + }, + }, + }, + }, + }, + }, + }, + arch: "x86_64", + virttype: "hvm", + targetMachine: "q35", + expectedResult: "pc-q35-2.12", + expectError: false, + }, + { + name: "machine not found returns error", + caps: createMockCaps("x86_64", "", + libvirtxml.CapsGuestMachine{Name: "pc"}), + arch: "x86_64", + virttype: "hvm", + targetMachine: "nonexistent", + expectError: true, + }, + { + name: "architecture not found returns error", + caps: createMockCaps("x86_64", ""), + arch: "invalid-arch", + virttype: "hvm", + targetMachine: "pc", + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := getCanonicalMachineName(tt.caps, tt.arch, tt.virttype, tt.targetMachine) + if tt.expectError { + assert.Error(t, err) + assert.Empty(t, result) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expectedResult, result) + } + }) + } +} + +func TestCreateCloudInitISO(t *testing.T) { + tests := []struct { + name string + vmConfig *vmConfig + expectError bool + }{ + { + name: "valid cloud-init data", + vmConfig: &vmConfig{ + name: "test-vm", + userData: "#cloud-config\nruncmd:\n - echo 'Hello World'\n", + }, + expectError: false, + }, + { + name: "empty user data", + vmConfig: &vmConfig{ + name: "test-vm", + userData: "", + }, + expectError: false, + }, + { + name: "large user data", + vmConfig: &vmConfig{ + name: "test-vm", + userData: "#cloud-config\n" + string(make([]byte, 10000)), + }, + expectError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + isoData, err := createCloudInitISO(tt.vmConfig) + if tt.expectError { + assert.Error(t, err) + assert.Nil(t, isoData) + } else { + assert.NoError(t, err) + assert.NotEmpty(t, isoData) + } }) } } @@ -213,7 +515,7 @@ func TestConfigVerifier(t *testing.T) { cfg := &Config{ URI: "qemu:///system", PoolName: "default", - NetworkName: "default", + NetworkName: testNetworkName, VolName: "podvm-base.qcow2", CPU: 1, Memory: 512, @@ -516,3 +818,357 @@ func TestCPUSetXMLMarshaling(t *testing.T) { }) } } + +func TestGetLaunchSecurityTypeInvalidURI(t *testing.T) { + _, err := GetLaunchSecurityType("invalid://uri") + assert.Error(t, err) +} + +func createMockCaps(arch, emulator string, machines ...libvirtxml.CapsGuestMachine) *libvirtxml.Caps { + return &libvirtxml.Caps{ + Guests: []libvirtxml.CapsGuest{ + { + OSType: "hvm", + Arch: libvirtxml.CapsGuestArch{ + Name: arch, + Emulator: emulator, + Machines: machines, + }, + }, + }, + } +} + +// TestCreateDomainXMLs390xWithMocks tests s390x domain XML generation using mocks +func TestCreateDomainXMLArchitecturesWithMocks(t *testing.T) { + tests := []struct { + name string + arch string + vmName string + cpu uint + mem uint + cidataDisk string + emulator string + machineName string + machineCanonical string + createFunc func(*libvirtClient, *domainConfig, *vmConfig) (*libvirtxml.Domain, error) + expectedFirmware string + expectSCSIController bool + }{ + { + name: "s390x architecture", + arch: "s390x", + vmName: "test-s390x-vm", + cpu: 2, + mem: 2048, + cidataDisk: testCiDataISO, + emulator: "/usr/bin/qemu-system-s390x", + machineName: "s390-ccw-virtio", + machineCanonical: "s390-ccw-virtio-rhel9.0.0", + createFunc: createDomainXMLs390x, + }, + { + name: "aarch64 architecture", + arch: "aarch64", + vmName: "test-aarch64-vm", + cpu: 4, + mem: 4096, + cidataDisk: testCloudInitISO, + emulator: "/usr/bin/qemu-system-aarch64", + machineName: "virt", + machineCanonical: "virt-4.2", + createFunc: createDomainXMLaarch64, + expectedFirmware: "efi", + expectSCSIController: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create mock capabilities + mockCaps := createMockCaps(tt.arch, tt.emulator, libvirtxml.CapsGuestMachine{ + Name: tt.machineName, + Canonical: tt.machineCanonical, + }) + + mockClient := &libvirtClient{ + caps: mockCaps, + networkName: testNetworkName, + } + + cfg := createTestDomainConfig(tt.vmName, tt.cpu, tt.mem, testNetworkName, tt.cidataDisk) + + vm := &vmConfig{} + + domain, err := tt.createFunc(mockClient, cfg, vm) + assert.NoError(t, err) + require.NotNil(t, domain) + + // Verify domain properties + assert.Equal(t, "kvm", domain.Type) + assert.Equal(t, tt.vmName, domain.Name) + assert.Equal(t, tt.cpu, domain.VCPU.Value) + assert.Equal(t, tt.mem, domain.Memory.Value) + assert.Equal(t, tt.arch, domain.OS.Type.Arch) + assert.Equal(t, tt.machineCanonical, domain.OS.Type.Machine) + + if tt.expectedFirmware != "" { + assert.Equal(t, tt.expectedFirmware, domain.OS.Firmware) + } + + // Verify disks + assert.Len(t, domain.Devices.Disks, 2) + assert.Equal(t, testBootDisk, domain.Devices.Disks[0].Source.File.File) + assert.Equal(t, "on", domain.Devices.Disks[0].Driver.IOMMU) + assert.Equal(t, tt.cidataDisk, domain.Devices.Disks[1].Source.File.File) + + // Verify network interface has IOMMU + assert.Len(t, domain.Devices.Interfaces, 1) + assert.Equal(t, "on", domain.Devices.Interfaces[0].Driver.IOMMU) + + // Verify SCSI controller if expected + if tt.expectSCSIController { + assert.Len(t, domain.Devices.Controllers, 1) + assert.Equal(t, "scsi", domain.Devices.Controllers[0].Type) + } + }) + } +} + +// TestCreateDomainXMLx86_64 tests x86_64 domain XML generation +func TestCreateDomainXMLx86_64(t *testing.T) { + mockCaps := createMockCaps("x86_64", "/usr/bin/qemu-system-x86_64") + + mockClient := &libvirtClient{ + caps: mockCaps, + networkName: testNetworkName, + } + + tests := []struct { + name string + cfg *domainConfig + vm *vmConfig + expectError bool + checkFirmware bool + expectedFW string + }{ + { + name: "basic x86_64 domain", + cfg: createTestDomainConfig("test-x86-vm", 2, 2048, testNetworkName, testCiDataISO), + vm: &vmConfig{ + launchSecurityType: NoLaunchSecurity, + }, + expectError: false, + }, + { + name: "x86_64 with firmware", + cfg: createTestDomainConfig("test-x86-fw-vm", 4, 4096, testNetworkName, testCiDataISO), + vm: &vmConfig{ + launchSecurityType: NoLaunchSecurity, + firmware: "/usr/share/OVMF/OVMF_CODE.fd", + }, + expectError: false, + checkFirmware: true, + expectedFW: "efi", + }, + { + name: "unsupported security type", + cfg: createTestDomainConfig("test-x86-sec-vm", 2, 2048, testNetworkName, testCiDataISO), + vm: &vmConfig{ + launchSecurityType: S390PV, // Not supported on x86_64 + }, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + domain, err := createDomainXMLx86_64(mockClient, tt.cfg, tt.vm) + + if tt.expectError { + assert.Error(t, err) + assert.Nil(t, domain) + return + } + + assert.NoError(t, err) + require.NotNil(t, domain) + + // Verify basic properties + assert.Equal(t, "kvm", domain.Type) + assert.Equal(t, tt.cfg.name, domain.Name) + assert.Equal(t, tt.cfg.cpu, domain.VCPU.Value) + assert.Equal(t, tt.cfg.mem, domain.Memory.Value) + assert.Equal(t, "x86_64", domain.OS.Type.Arch) + + // Verify disks + assert.Len(t, domain.Devices.Disks, 2) + assert.Equal(t, tt.cfg.bootDisk, domain.Devices.Disks[0].Source.File.File) + assert.Equal(t, tt.cfg.cidataDisk, domain.Devices.Disks[1].Source.File.File) + + // Check firmware if specified + if tt.checkFirmware { + assert.NotEmpty(t, domain.OS.Loader) + assert.Equal(t, tt.vm.firmware, domain.OS.Loader.Path) + assert.Equal(t, tt.expectedFW, domain.OS.Firmware) + } + }) + } +} + +// TestCreateDomainXML tests the architecture-based domain XML dispatcher +func TestCreateDomainXML(t *testing.T) { + tests := []struct { + name string + arch string + expectedArch string + }{ + { + name: "s390x architecture", + arch: "s390x", + expectedArch: "s390x", + }, + { + name: "aarch64 architecture", + arch: "aarch64", + expectedArch: "aarch64", + }, + { + name: "x86_64 architecture (default)", + arch: "x86_64", + expectedArch: "x86_64", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create appropriate mock capabilities using helper function + var mockCaps *libvirtxml.Caps + switch tt.arch { + case "s390x": + mockCaps = createMockCaps("s390x", "/usr/bin/qemu-system-s390x", + libvirtxml.CapsGuestMachine{Name: "s390-ccw-virtio", Canonical: "s390-ccw-virtio-rhel9.0.0"}) + case "aarch64": + mockCaps = createMockCaps("aarch64", "/usr/bin/qemu-system-aarch64", + libvirtxml.CapsGuestMachine{Name: "virt", Canonical: "virt-4.2"}) + default: + mockCaps = createMockCaps("x86_64", "/usr/bin/qemu-system-x86_64") + } + + mockClient := &libvirtClient{ + caps: mockCaps, + networkName: testNetworkName, + nodeInfo: &libvirt.NodeInfo{Model: tt.arch}, + } + + cfg := createTestDomainConfig("test-vm", 2, 2048, testNetworkName, testCiDataISO) + + vm := &vmConfig{ + launchSecurityType: NoLaunchSecurity, + } + + domain, err := createDomainXML(mockClient, cfg, vm) + assert.NoError(t, err) + require.NotNil(t, domain) + assert.Equal(t, tt.expectedArch, domain.OS.Type.Arch) + }) + } +} + +// TestVerifyDomainXMLIOMMU tests IOMMU verification for s390x and aarch64 +func TestVerifyDomainXMLIOMMU(t *testing.T) { + tests := []struct { + name string + domain *libvirtxml.Domain + expectError bool + errorMsg string + }{ + { + name: "s390x with proper IOMMU on disks and interfaces", + domain: &libvirtxml.Domain{ + OS: &libvirtxml.DomainOS{ + Type: &libvirtxml.DomainOSType{Arch: "s390x"}, + }, + Devices: &libvirtxml.DomainDeviceList{ + Disks: []libvirtxml.DomainDisk{ + { + Target: &libvirtxml.DomainDiskTarget{Bus: "virtio"}, + Driver: &libvirtxml.DomainDiskDriver{IOMMU: "on"}, + }, + }, + Interfaces: []libvirtxml.DomainInterface{ + { + Model: &libvirtxml.DomainInterfaceModel{Type: "virtio"}, + Driver: &libvirtxml.DomainInterfaceDriver{IOMMU: "on"}, + }, + }, + }, + }, + expectError: false, + }, + { + name: "s390x missing IOMMU on disk", + domain: &libvirtxml.Domain{ + OS: &libvirtxml.DomainOS{ + Type: &libvirtxml.DomainOSType{Arch: "s390x"}, + }, + Devices: &libvirtxml.DomainDeviceList{ + Disks: []libvirtxml.DomainDisk{ + { + Target: &libvirtxml.DomainDiskTarget{Bus: "virtio"}, + Driver: &libvirtxml.DomainDiskDriver{}, // Missing IOMMU + }, + }, + }, + }, + expectError: true, + errorMsg: "does not have IOMMU assigned", + }, + { + name: "aarch64 missing IOMMU on interface", + domain: &libvirtxml.Domain{ + OS: &libvirtxml.DomainOS{ + Type: &libvirtxml.DomainOSType{Arch: "aarch64"}, + }, + Devices: &libvirtxml.DomainDeviceList{ + Interfaces: []libvirtxml.DomainInterface{ + { + Model: &libvirtxml.DomainInterfaceModel{Type: "virtio"}, + Driver: &libvirtxml.DomainInterfaceDriver{}, // Missing IOMMU + }, + }, + }, + }, + expectError: true, + errorMsg: "does not have IOMMU assigned", + }, + { + name: "x86_64 does not require IOMMU", + domain: &libvirtxml.Domain{ + OS: &libvirtxml.DomainOS{ + Type: &libvirtxml.DomainOSType{Arch: "x86_64"}, + }, + Devices: &libvirtxml.DomainDeviceList{ + Disks: []libvirtxml.DomainDisk{ + { + Target: &libvirtxml.DomainDiskTarget{Bus: "virtio"}, + Driver: &libvirtxml.DomainDiskDriver{}, // No IOMMU required + }, + }, + }, + }, + expectError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := verifyDomainXML(tt.domain) + if tt.expectError { + assert.ErrorContains(t, err, tt.errorMsg) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/src/cloud-providers/libvirt/manager_test.go b/src/cloud-providers/libvirt/manager_test.go new file mode 100644 index 0000000000..660f3e15a6 --- /dev/null +++ b/src/cloud-providers/libvirt/manager_test.go @@ -0,0 +1,324 @@ +// (C) Copyright Confidential Containers Contributors +// SPDX-License-Identifier: Apache-2.0 + +package libvirt + +import ( + "flag" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func resetLibvirtConfig() { + libvirtcfg = Config{ + URI: defaultURI, + PoolName: defaultPoolName, + NetworkName: defaultNetworkName, + DataDir: defaultDataDir, + VolName: defaultVolName, + LaunchSecurity: defaultLaunchSecurity, + Firmware: defaultFirmware, + CPU: 2, + Memory: 8192, + DisableCVM: true, + } +} + +// setupManagerTest creates a fresh Manager with flags for testing +func setupManagerTest(t *testing.T) (*Manager, *flag.FlagSet) { + t.Helper() + resetLibvirtConfig() + manager := &Manager{} + flags := flag.NewFlagSet("test", flag.ContinueOnError) + manager.ParseCmd(flags) + return manager, flags +} + +func TestManagerParseCmdWithEnvVars(t *testing.T) { + // Set environment variables + t.Setenv("LIBVIRT_URI", "qemu+ssh://testhost/system") + t.Setenv("LIBVIRT_POOL", "env-pool") + t.Setenv("LIBVIRT_NET", "env-network") + t.Setenv("LIBVIRT_VOL_NAME", "env-vol.qcow2") + t.Setenv("LIBVIRT_LAUNCH_SECURITY", "sev") + t.Setenv("LIBVIRT_EFI_FIRMWARE", "/env/firmware.fd") + t.Setenv("LIBVIRT_CPU", "8") + t.Setenv("LIBVIRT_MEMORY", "16384") + t.Setenv("DISABLECVM", "false") + + _, _ = setupManagerTest(t) + + // Verify environment variables were applied + assert.Equal(t, "qemu+ssh://testhost/system", libvirtcfg.URI) + assert.Equal(t, "env-pool", libvirtcfg.PoolName) + assert.Equal(t, "env-network", libvirtcfg.NetworkName) + assert.Equal(t, "env-vol.qcow2", libvirtcfg.VolName) + assert.Equal(t, "sev", libvirtcfg.LaunchSecurity) + assert.Equal(t, "/env/firmware.fd", libvirtcfg.Firmware) + assert.Equal(t, uint(8), libvirtcfg.CPU) + assert.Equal(t, uint(16384), libvirtcfg.Memory) + assert.False(t, libvirtcfg.DisableCVM) +} + +func TestManagerParseCmdFlagOverridesEnv(t *testing.T) { + // Set environment variable + t.Setenv("LIBVIRT_URI", "qemu+ssh://envhost/system") + t.Setenv("LIBVIRT_CPU", "8") + + _, flags := setupManagerTest(t) + + // Verify env var was applied initially + assert.Equal(t, "qemu+ssh://envhost/system", libvirtcfg.URI) + assert.Equal(t, uint(8), libvirtcfg.CPU) + + // Override with flag + err := flags.Set("uri", "qemu:///system") + require.NoError(t, err) + err = flags.Set("cpu", "4") + require.NoError(t, err) + + // Verify flag overrides env var + assert.Equal(t, "qemu:///system", libvirtcfg.URI) + assert.Equal(t, uint(4), libvirtcfg.CPU) +} + +func TestManagerParseCmdInvalidValues(t *testing.T) { + tests := []struct { + name string + flagName string + invalidValue string + description string + }{ + { + name: "invalid CPU value", + flagName: "cpu", + invalidValue: "invalid", + description: "non-numeric CPU value should be rejected", + }, + { + name: "invalid memory value", + flagName: "memory", + invalidValue: "not-a-number", + description: "non-numeric memory value should be rejected", + }, + { + name: "invalid bool value", + flagName: "disable-cvm", + invalidValue: "maybe", + description: "invalid boolean value should be rejected", + }, + { + name: "negative CPU value", + flagName: "cpu", + invalidValue: "-1", + description: "negative CPU value should be rejected", + }, + { + name: "negative memory value", + flagName: "memory", + invalidValue: "-1", + description: "negative memory value should be rejected", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + _, flags := setupManagerTest(t) + + err := flags.Set(tc.flagName, tc.invalidValue) + assert.Error(t, err, tc.description) + }) + } +} + +func TestManagerParseCmdEmptyStringValues(t *testing.T) { + _, flags := setupManagerTest(t) + + // Set empty string values (should be allowed) + err := flags.Set("uri", "") + require.NoError(t, err) + err = flags.Set("pool-name", "") + require.NoError(t, err) + err = flags.Set("launch-security", "") + require.NoError(t, err) + + // Verify empty strings are set + assert.Equal(t, "", libvirtcfg.URI) + assert.Equal(t, "", libvirtcfg.PoolName) + assert.Equal(t, "", libvirtcfg.LaunchSecurity) +} + +func TestManagerLoadEnv(t *testing.T) { + manager, _ := setupManagerTest(t) + // LoadEnv should do nothing (it's a no-op) + manager.LoadEnv() + // No assertion needed, just verify it doesn't panic +} + +func TestManagerGetConfig(t *testing.T) { + manager, _ := setupManagerTest(t) + config := manager.GetConfig() + assert.NotNil(t, config) + assert.Equal(t, &libvirtcfg, config) +} + +func TestManagerNewProvider(t *testing.T) { + tests := []struct { + name string + setupConfig func(*testing.T, *flag.FlagSet) + expectError bool + description string + }{ + { + name: "valid config", + setupConfig: func(t *testing.T, flags *flag.FlagSet) { + resetLibvirtConfig() + checkConfig(t) + require.NoError(t, flags.Set("uri", testCfg.URI)) + require.NoError(t, flags.Set("pool-name", testCfg.PoolName)) + require.NoError(t, flags.Set("network-name", testCfg.NetworkName)) + require.NoError(t, flags.Set("vol-name", testCfg.VolName)) + }, + expectError: false, + description: "should succeed with valid config", + }, + { + name: "invalid URI", + setupConfig: func(t *testing.T, flags *flag.FlagSet) { + require.NoError(t, flags.Set("uri", "invalid://uri")) + }, + expectError: true, + description: "should fail with invalid URI", + }, + { + name: "empty URI", + setupConfig: func(t *testing.T, flags *flag.FlagSet) { + require.NoError(t, flags.Set("uri", "")) + }, + expectError: true, + description: "should fail with empty URI", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + manager, flags := setupManagerTest(t) + tc.setupConfig(t, flags) + + provider, err := manager.NewProvider() + if tc.expectError { + assert.Error(t, err, tc.description) + } else { + require.NoError(t, err, tc.description) + assert.NotNil(t, provider) + } + }) + } +} + +func TestDefaultConstants(t *testing.T) { + // Test all constants in a single assertion block + assert.Equal(t, "qemu+ssh://root@192.168.122.1/system?no_verify=1", defaultURI) + assert.Equal(t, "default", defaultPoolName) + assert.Equal(t, "default", defaultNetworkName) + assert.Equal(t, "/var/lib/libvirt/images", defaultDataDir) + assert.Equal(t, "podvm-base.qcow2", defaultVolName) + assert.Equal(t, "", defaultLaunchSecurity) + assert.Equal(t, "/usr/share/OVMF/OVMF_CODE_4M.fd", defaultFirmware) + assert.Equal(t, "2", defaultCPU) + assert.Equal(t, "8192", defaultMemory) +} + +func TestManagerParseCmdFlags(t *testing.T) { + tests := []struct { + name string + flagName string + flagValue string + expectedValue interface{} + getActual func() interface{} + }{ + { + name: "uri flag", + flagName: "uri", + flagValue: "qemu:///system", + expectedValue: "qemu:///system", + getActual: func() interface{} { return libvirtcfg.URI }, + }, + { + name: "pool-name flag", + flagName: "pool-name", + flagValue: "test-pool", + expectedValue: "test-pool", + getActual: func() interface{} { return libvirtcfg.PoolName }, + }, + { + name: "network-name flag", + flagName: "network-name", + flagValue: "test-network", + expectedValue: "test-network", + getActual: func() interface{} { return libvirtcfg.NetworkName }, + }, + { + name: "vol-name flag", + flagName: "vol-name", + flagValue: "test-vol.qcow2", + expectedValue: "test-vol.qcow2", + getActual: func() interface{} { return libvirtcfg.VolName }, + }, + { + name: "launch-security flag", + flagName: "launch-security", + flagValue: "s390-pv", + expectedValue: "s390-pv", + getActual: func() interface{} { return libvirtcfg.LaunchSecurity }, + }, + { + name: "firmware flag", + flagName: "firmware", + flagValue: "/custom/path/to/firmware.fd", + expectedValue: "/custom/path/to/firmware.fd", + getActual: func() interface{} { return libvirtcfg.Firmware }, + }, + { + name: "data-dir flag", + flagName: "data-dir", + flagValue: "/custom/data/dir", + expectedValue: "/custom/data/dir", + getActual: func() interface{} { return libvirtcfg.DataDir }, + }, + { + name: "cpu flag", + flagName: "cpu", + flagValue: "4", + expectedValue: uint(4), + getActual: func() interface{} { return libvirtcfg.CPU }, + }, + { + name: "memory flag", + flagName: "memory", + flagValue: "4096", + expectedValue: uint(4096), + getActual: func() interface{} { return libvirtcfg.Memory }, + }, + { + name: "disable-cvm flag", + flagName: "disable-cvm", + flagValue: "false", + expectedValue: false, + getActual: func() interface{} { return libvirtcfg.DisableCVM }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + _, flags := setupManagerTest(t) + + err := flags.Set(tc.flagName, tc.flagValue) + require.NoError(t, err) + + assert.Equal(t, tc.expectedValue, tc.getActual()) + }) + } +} diff --git a/src/csi-wrapper/Dockerfile.csi_wrappers b/src/csi-wrapper/Dockerfile.csi_wrappers index d273f5ee25..bee6732dbf 100644 --- a/src/csi-wrapper/Dockerfile.csi_wrappers +++ b/src/csi-wrapper/Dockerfile.csi_wrappers @@ -7,15 +7,15 @@ ARG SOURCE_FROM=remote ##### Builder Dev Image ##### -# golang:1.25.11 -FROM --platform=${BUILDPLATFORM} golang@sha256:f188e8c16ea47a8b22d2bdcf6d9bcd07b63ea7876c199749c07bf31e0ab33bad AS builder-local +# golang:1.25.12 +FROM --platform=${BUILDPLATFORM} golang@sha256:d7912cedddfa15b2900a8dfb7187df0af5ec2cb424a371139b5b352fd3e6b740 AS builder-local WORKDIR /src COPY csi-wrapper ./cloud-api-adaptor/src/csi-wrapper/ COPY cloud-api-adaptor ./cloud-api-adaptor/src/cloud-api-adaptor ##### Builder Release Image ##### -# golang:1.25.11 -FROM --platform=${BUILDPLATFORM} golang@sha256:f188e8c16ea47a8b22d2bdcf6d9bcd07b63ea7876c199749c07bf31e0ab33bad AS builder-remote +# golang:1.25.12 +FROM --platform=${BUILDPLATFORM} golang@sha256:d7912cedddfa15b2900a8dfb7187df0af5ec2cb424a371139b5b352fd3e6b740 AS builder-remote ARG BINARY ARG CAA_SRC="https://github.com/confidential-containers/cloud-api-adaptor" ARG CAA_SRC_REF="main" diff --git a/src/csi-wrapper/go.mod b/src/csi-wrapper/go.mod index 1f0586629c..50be16def7 100644 --- a/src/csi-wrapper/go.mod +++ b/src/csi-wrapper/go.mod @@ -1,6 +1,6 @@ module github.com/confidential-containers/cloud-api-adaptor/src/csi-wrapper -go 1.25.11 +go 1.25.12 require ( github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor v0.0.0-00010101000000-000000000000 @@ -9,8 +9,8 @@ require ( github.com/gofrs/uuid v4.4.0+incompatible github.com/golang/glog v1.2.5 github.com/golang/protobuf v1.5.4 - github.com/kata-containers/kata-containers/src/runtime v0.0.0-20260422184550-8dccf4cf37ae - google.golang.org/grpc v1.80.0 + github.com/kata-containers/kata-containers/src/runtime v0.0.0-20260519201048-cec98e0d976b + google.golang.org/grpc v1.82.1 k8s.io/apimachinery v0.35.2 k8s.io/client-go v0.35.2 k8s.io/code-generator v0.35.2 @@ -35,21 +35,21 @@ require ( github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect github.com/spf13/pflag v1.0.9 // indirect github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.35.0 // indirect - golang.org/x/net v0.55.0 // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/net v0.56.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.45.0 // indirect - golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/term v0.44.0 // indirect + golang.org/x/text v0.39.0 // indirect golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.44.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect + golang.org/x/tools v0.47.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/src/csi-wrapper/go.sum b/src/csi-wrapper/go.sum index f00d11c6c3..2dc7a83af4 100644 --- a/src/csi-wrapper/go.sum +++ b/src/csi-wrapper/go.sum @@ -47,8 +47,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kata-containers/kata-containers/src/runtime v0.0.0-20260422184550-8dccf4cf37ae h1:52j1vpTT7yfFrDEjVbvKnasG8I5Ca7+pYcNx4AN/1Tw= -github.com/kata-containers/kata-containers/src/runtime v0.0.0-20260422184550-8dccf4cf37ae/go.mod h1:Dnl25Qo2S1qiYQX4Ytk7U4oxT2+eRPFzP8K8idi8WA8= +github.com/kata-containers/kata-containers/src/runtime v0.0.0-20260519201048-cec98e0d976b h1:My9k9WnOHoGFGg0tJ0CgzaCbBkj88nIBbBXTKDCL2fE= +github.com/kata-containers/kata-containers/src/runtime v0.0.0-20260519201048-cec98e0d976b/go.mod h1:KxmhVNDCaSry73zZ59oDIA7gZldHI7UvhO6TtlWv8Lg= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -74,15 +74,14 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= @@ -95,8 +94,8 @@ go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWv go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -105,35 +104,34 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= -golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= +golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE= +google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -143,7 +141,6 @@ gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnf gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.35.2 h1:tW7mWc2RpxW7HS4CoRXhtYHSzme1PN1UjGHJ1bdrtdw= diff --git a/src/peerpod-ctrl/Dockerfile b/src/peerpod-ctrl/Dockerfile index 86793131a3..ed17fff936 100644 --- a/src/peerpod-ctrl/Dockerfile +++ b/src/peerpod-ctrl/Dockerfile @@ -1,6 +1,6 @@ # Build the manager binary -# golang:1.25.11 -FROM --platform=$TARGETPLATFORM golang@sha256:f188e8c16ea47a8b22d2bdcf6d9bcd07b63ea7876c199749c07bf31e0ab33bad AS builder +# golang:1.25.12 +FROM --platform=$TARGETPLATFORM golang@sha256:d7912cedddfa15b2900a8dfb7187df0af5ec2cb424a371139b5b352fd3e6b740 AS builder ARG TARGETOS ARG TARGETARCH ARG CGO_ENABLED=1 @@ -35,8 +35,8 @@ COPY peerpod-ctrl/controllers/ controllers/ RUN CC=gcc CGO_ENABLED=${CGO_ENABLED} GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build ${GOFLAGS} -a -o manager main.go # Target Image -# debian:trixie-slim (matches golang:1.25.11 base for library compatibility) -FROM --platform=$TARGETPLATFORM debian@sha256:109e2c65005bf160609e4ba6acf7783752f8502ad218e298253428690b9eaa4b +# debian:trixie-slim (matches golang:1.25.12 base for library compatibility) +FROM --platform=$TARGETPLATFORM debian@sha256:28de0877c2189802884ccd20f15ee41c203573bd87bb6b883f5f46362d24c5c2 ARG CGO_ENABLED=1 RUN if [ "$CGO_ENABLED" = 1 ] ; then \ diff --git a/src/peerpod-ctrl/chart/Chart.yaml b/src/peerpod-ctrl/chart/Chart.yaml index 6035545c0b..6c1e254509 100644 --- a/src/peerpod-ctrl/chart/Chart.yaml +++ b/src/peerpod-ctrl/chart/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: peerpodctrl description: Controller for cleaning up dangling peer pod cloud resources type: application -version: 0.2.0 -appVersion: "v0.20.0" +version: 0.3.1 +appVersion: "v0.21.1" keywords: - confidential-containers diff --git a/src/peerpod-ctrl/chart/values.yaml b/src/peerpod-ctrl/chart/values.yaml index 77bd50af6b..fa6c760294 100644 --- a/src/peerpod-ctrl/chart/values.yaml +++ b/src/peerpod-ctrl/chart/values.yaml @@ -4,7 +4,7 @@ namePrefix: peerpodctrl- # PeerPod controller image image: repository: quay.io/confidential-containers/peerpod-ctrl - tag: 2d2e7c2c0736ec41c889cd98442a598b8b93bc0b + tag: f5dd0b2657a76482c6acabe0285cc87eb5d49473 pullPolicy: IfNotPresent # kube-rbac-proxy: Sidecar container that protects the /metrics endpoint with RBAC authentication diff --git a/src/peerpod-ctrl/go.mod b/src/peerpod-ctrl/go.mod index a3d5dfacf0..1c940e6f8f 100644 --- a/src/peerpod-ctrl/go.mod +++ b/src/peerpod-ctrl/go.mod @@ -1,6 +1,6 @@ module github.com/confidential-containers/cloud-api-adaptor/src/peerpod-ctrl -go 1.25.11 +go 1.25.12 require ( github.com/confidential-containers/cloud-api-adaptor/src/cloud-providers v0.0.0-00010101000000-000000000000 @@ -69,14 +69,14 @@ require ( go.opentelemetry.io/otel/trace v1.43.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.35.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/tools v0.44.0 // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/tools v0.47.0 // indirect google.golang.org/api v0.274.0 // indirect google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/grpc v1.80.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/grpc v1.82.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect @@ -146,12 +146,12 @@ require ( go.mongodb.org/mongo-driver v1.17.6 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.52.0 // indirect - golang.org/x/net v0.55.0 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sys v0.45.0 // indirect - golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/term v0.44.0 // indirect + golang.org/x/text v0.39.0 // indirect golang.org/x/time v0.15.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/protobuf v1.36.11 // indirect @@ -159,7 +159,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.35.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect; indirect// indirect + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect libvirt.org/go/libvirt v1.11010.0 // indirect libvirt.org/go/libvirtxml v1.11010.0 // indirect diff --git a/src/peerpod-ctrl/go.sum b/src/peerpod-ctrl/go.sum index 53a2052980..d4713439e3 100644 --- a/src/peerpod-ctrl/go.sum +++ b/src/peerpod-ctrl/go.sum @@ -143,8 +143,8 @@ github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyM github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -153,11 +153,11 @@ github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= -github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= -github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= -github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -423,8 +423,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= -golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -435,8 +435,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -458,8 +458,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= @@ -474,8 +474,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -497,8 +497,8 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -512,8 +512,8 @@ golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= -golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -525,8 +525,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= +golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -541,8 +541,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -558,16 +558,16 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0= google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE= +google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/src/webhook/Dockerfile b/src/webhook/Dockerfile index 00db69338c..bccf1c8ad0 100644 --- a/src/webhook/Dockerfile +++ b/src/webhook/Dockerfile @@ -1,6 +1,6 @@ # Build the manager binary -# golang:1.25.11 -FROM --platform=$BUILDPLATFORM golang@sha256:f188e8c16ea47a8b22d2bdcf6d9bcd07b63ea7876c199749c07bf31e0ab33bad AS builder +# golang:1.25.12 +FROM --platform=$BUILDPLATFORM golang@sha256:d7912cedddfa15b2900a8dfb7187df0af5ec2cb424a371139b5b352fd3e6b740 AS builder WORKDIR /workspace # Copy the Go Modules manifests diff --git a/src/webhook/Makefile b/src/webhook/Makefile index 46b671fe56..48e39b118e 100644 --- a/src/webhook/Makefile +++ b/src/webhook/Makefile @@ -167,11 +167,19 @@ kind-deploy: docker-build kind-load deploy ## deploy the webhook in the local ki deploy-cert-manager: ## Deploy cert-manager for webhook. curl -fsSL -o cmctl https://github.com/cert-manager/cmctl/releases/latest/download/cmctl_${OS}_${ARCH} chmod +x cmctl - # Deploy cert-manager - kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml + # Deploy cert-manager (retry to tolerate transient etcd timeouts) + @for i in 1 2 3; do \ + echo "Applying cert-manager manifest (attempt $$i)..."; \ + kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml && { \ + echo "cert-manager applied successfully"; break; }; \ + if [ $$i -eq 3 ]; then \ + echo "cert-manager apply failed after 3 attempts"; exit 1; \ + fi; \ + echo "Apply failed, retrying in 10s..."; sleep 10; \ + done # Wait for service to be up - kubectl wait --timeout=360s -n cert-manager endpoints/cert-manager --for=jsonpath='{.subsets[0].addresses[0].ip}' - kubectl wait --timeout=360s -n cert-manager endpoints/cert-manager-webhook --for=jsonpath='{.subsets[0].addresses[0].ip}' + kubectl wait --timeout=360s -n cert-manager --for=condition=Available deployment/cert-manager + kubectl wait --timeout=360s -n cert-manager --for=condition=Available deployment/cert-manager-webhook # Wait for few seconds for the cert-manager API to be ready # otherwise you'll hit the error "x509: certificate signed by unknown authority" # Best is to use cmctl - https://cert-manager.io/docs/installation/kubectl/#2-optional-wait-for-cert-manager-webhook-to-be-ready diff --git a/src/webhook/chart/Chart.yaml b/src/webhook/chart/Chart.yaml index 2357be283e..b0275bf360 100644 --- a/src/webhook/chart/Chart.yaml +++ b/src/webhook/chart/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: peerpods-webhook description: Mutating webhook that modifies pod specs to use peer pods runtime and resources type: application -version: 0.2.0 -appVersion: "v0.20.0" +version: 0.3.1 +appVersion: "v0.21.1" keywords: - confidential-containers diff --git a/src/webhook/chart/values.yaml b/src/webhook/chart/values.yaml index 608aa48a11..42a2fbefa3 100644 --- a/src/webhook/chart/values.yaml +++ b/src/webhook/chart/values.yaml @@ -15,7 +15,7 @@ replicas: 2 # Webhook image image: repository: quay.io/confidential-containers/peer-pods-webhook - tag: 2d2e7c2c0736ec41c889cd98442a598b8b93bc0b + tag: f5dd0b2657a76482c6acabe0285cc87eb5d49473 pullPolicy: IfNotPresent # Manager container resource limits and requests diff --git a/src/webhook/go.mod b/src/webhook/go.mod index 3d0a1c3a48..c0bc273d66 100644 --- a/src/webhook/go.mod +++ b/src/webhook/go.mod @@ -1,6 +1,6 @@ module github.com/confidential-containers/cloud-api-adaptor/src/webhook -go 1.25.11 +go 1.25.12 require ( k8s.io/api v0.35.2 @@ -46,11 +46,11 @@ require ( go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/net v0.55.0 // indirect - golang.org/x/oauth2 v0.32.0 // indirect - golang.org/x/sync v0.20.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.21.0 // indirect golang.org/x/sys v0.45.0 // indirect golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect + golang.org/x/text v0.39.0 // indirect golang.org/x/time v0.9.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/protobuf v1.36.11 // indirect diff --git a/src/webhook/go.sum b/src/webhook/go.sum index 78a6e15367..47b938cb02 100644 --- a/src/webhook/go.sum +++ b/src/webhook/go.sum @@ -111,24 +111,24 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= -golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= -golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= +golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=