├── hack ├── compose │ ├── docker-compose.override.yml │ └── docker-compose.yml ├── test │ ├── configpatch.yaml │ ├── manifests │ │ ├── cdi-cr.yaml │ │ └── local-path-storage.yaml │ └── integration.sh ├── release.toml ├── certs │ ├── localhost.pem │ ├── localhost-key.pem │ ├── key.public │ └── key.private ├── govulncheck.sh └── release.sh ├── .gitignore ├── .license-header.go.txt ├── .markdownlint.json ├── .dockerignore ├── internal └── pkg │ └── provider │ ├── meta │ └── meta.go │ ├── data │ ├── schema.json │ └── data.go │ ├── resources │ └── machine.go │ └── provision.go ├── .codecov.yml ├── api └── specs │ ├── specs.proto │ ├── specs.pb.go │ └── specs_vtproto.pb.go ├── .sops.yaml ├── .github ├── workflows │ ├── lock.yml │ ├── stale.yml │ ├── slack-notify-ci-failure.yaml │ ├── slack-notify.yaml │ └── ci.yaml └── renovate.json ├── .conform.yaml ├── README.md ├── cmd └── omni-infra-provider-kubevirt │ ├── data │ └── icon.svg │ └── main.go ├── .kres.yaml ├── .secrets.yaml ├── .golangci.yml ├── go.mod ├── Dockerfile ├── Makefile ├── LICENSE └── go.sum /hack/compose/docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | omni-infra-provider-kubevirt: 3 | command: >- 4 | args: 5 | --omni-api-endpoint=https://localhost:8099 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2024-09-30T14:59:39Z by kres 8be5fa7. 4 | 5 | _out 6 | hack/compose/docker-compose.override.yml 7 | -------------------------------------------------------------------------------- /hack/test/configpatch.yaml: -------------------------------------------------------------------------------- 1 | cluster: 2 | network: 3 | podSubnets: 4 | - 10.10.0.0/17 5 | serviceSubnets: 6 | - 10.10.128.0/17 7 | apiServer: 8 | disablePodSecurityPolicy: true 9 | -------------------------------------------------------------------------------- /.license-header.go.txt: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2024-09-30T14:56:28Z by kres 8be5fa7. 4 | 5 | { 6 | "MD013": false, 7 | "MD033": false, 8 | "default": true 9 | } 10 | -------------------------------------------------------------------------------- /hack/release.toml: -------------------------------------------------------------------------------- 1 | # commit to be tagged for the new release 2 | commit = "HEAD" 3 | 4 | project_name = "" 5 | github_repo = "/" 6 | match_deps = "^github.com/(/[a-zA-Z0-9-]+)$" 7 | 8 | # previous = - 9 | # pre_release = true 10 | 11 | # [notes] 12 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-09-04T10:40:31Z by kres 784fa1f. 4 | 5 | * 6 | !api 7 | !cmd 8 | !internal 9 | !go.mod 10 | !go.sum 11 | !.golangci.yml 12 | !README.md 13 | !.markdownlint.json 14 | !hack/govulncheck.sh 15 | -------------------------------------------------------------------------------- /internal/pkg/provider/meta/meta.go: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | // Package meta contains meta information about the provider. 6 | package meta 7 | 8 | // ProviderID is the ID of the provider. 9 | var ProviderID = "kubevirt" 10 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2024-09-30T14:56:28Z by kres 8be5fa7. 4 | 5 | codecov: 6 | require_ci_to_pass: false 7 | 8 | coverage: 9 | status: 10 | project: 11 | default: 12 | target: 50% 13 | threshold: 0.5% 14 | base: auto 15 | if_ci_failed: success 16 | patch: off 17 | 18 | comment: false 19 | -------------------------------------------------------------------------------- /hack/test/manifests/cdi-cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cdi.kubevirt.io/v1beta1 2 | kind: CDI 3 | metadata: 4 | name: cdi 5 | spec: 6 | config: 7 | featureGates: 8 | - HonorWaitForFirstConsumer 9 | imagePullPolicy: IfNotPresent 10 | infra: 11 | nodeSelector: 12 | kubernetes.io/os: linux 13 | tolerations: 14 | - key: CriticalAddonsOnly 15 | operator: Exists 16 | workload: 17 | nodeSelector: 18 | kubernetes.io/os: linux 19 | -------------------------------------------------------------------------------- /api/specs/specs.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package emuspecs; 3 | 4 | option go_package = "github.com/siderolabs/omni-infra-provider-kubevirt/api/specs"; 5 | 6 | import "google/protobuf/timestamp.proto"; 7 | import "google/protobuf/duration.proto"; 8 | 9 | // MachineSpec is stored in Omni in the infra provisioner state. 10 | message MachineSpec { 11 | string uuid = 1; 12 | string schematic = 2; 13 | string talos_version = 3; 14 | string volume_id = 4; 15 | } 16 | -------------------------------------------------------------------------------- /.sops.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2024-04-18T18:20:58Z by kres 92eef68-dirty. 4 | 5 | creation_rules: 6 | - age: age1xrpa9ujxxcj2u2gzfrzv8mxak4rts94a6y60ypurv6rs5cpr4e4sg95f0k 7 | # order: Andrey, Noel, Artem, Utku, Dmitriy 8 | pgp: >- 9 | 15D5721F5F5BAF121495363EFE042E3D4085A811, 10 | CC51116A94490FA6FB3C18EB2401FCAE863A06CA, 11 | 4919F560F0D35F80CF382D76E084A2DF1143C14D, 12 | 966BC282A680D8BB3E8363E865933E76F0549B0D, 13 | AA5213AF261C1977AF38B03A94B473337258BFD5 -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-09-04T10:40:31Z by kres 784fa1f. 4 | 5 | "on": 6 | schedule: 7 | - cron: 0 2 * * * 8 | name: Lock old issues 9 | permissions: 10 | issues: write 11 | jobs: 12 | action: 13 | runs-on: 14 | - ubuntu-latest 15 | steps: 16 | - name: Lock old issues 17 | uses: dessant/lock-threads@v5.0.1 18 | with: 19 | issue-inactive-days: "60" 20 | log-output: "true" 21 | process-only: issues 22 | -------------------------------------------------------------------------------- /internal/pkg/provider/data/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "cores": { 5 | "type": "integer", 6 | "minimum": 1 7 | }, 8 | "memory": { 9 | "type": "integer", 10 | "minimum": 2048 11 | }, 12 | "architecture": { 13 | "enum": ["amd64", "arm64"] 14 | }, 15 | "disk_size": { 16 | "type": "integer", 17 | "minimum": 5, 18 | "description": "In GB" 19 | }, 20 | "network_binding": { 21 | "enum": ["bridge", "passt"], 22 | "default": "bridge" 23 | } 24 | }, 25 | "required": [ 26 | "cores", 27 | "memory", 28 | "architecture", 29 | "disk_size" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /internal/pkg/provider/data/data.go: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | // Package data defines the structures and interfaces for custom provider data. 6 | // Each provider can have its own machine configuration schema. 7 | // When a provider starts, it reports its data schema back to Omni. 8 | // Omni then uses this schema to render the appropriate UI and validate MachineRequests 9 | package data 10 | 11 | import ( 12 | _ "embed" 13 | ) 14 | 15 | //go:embed schema.json 16 | var Schema []byte 17 | 18 | // Data and schema.json should be in sync. 19 | type Data struct { 20 | Architecture string `yaml:"architecture"` 21 | NetworkBinding string `yaml:"network_binding,omitempty"` 22 | Cores int `yaml:"cores"` 23 | DiskSize int `yaml:"disk_size"` 24 | Memory uint64 `yaml:"memory"` 25 | } 26 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "description": "THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.", 4 | "prHeader": "Update Request | Renovate Bot", 5 | "extends": [ 6 | ":dependencyDashboard", 7 | ":gitSignOff", 8 | ":semanticCommitScopeDisabled", 9 | "schedule:earlyMondays" 10 | ], 11 | "packageRules": [ 12 | { 13 | "groupName": "dependencies", 14 | "matchUpdateTypes": [ 15 | "major", 16 | "minor", 17 | "patch", 18 | "pin", 19 | "digest" 20 | ] 21 | }, 22 | { 23 | "enabled": false, 24 | "matchFileNames": [ 25 | "Dockerfile" 26 | ] 27 | }, 28 | { 29 | "enabled": false, 30 | "matchFileNames": [ 31 | ".github/workflows/*.yaml" 32 | ] 33 | } 34 | ], 35 | "separateMajorMinor": false 36 | } 37 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-11-06T14:58:30Z by kres 4ba9b0c. 4 | 5 | "on": 6 | schedule: 7 | - cron: 30 1 * * * 8 | name: Close stale issues and PRs 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | jobs: 13 | stale: 14 | runs-on: 15 | - ubuntu-latest 16 | steps: 17 | - name: Close stale issues and PRs 18 | uses: actions/stale@v10.1.0 19 | with: 20 | close-issue-message: This issue was closed because it has been stalled for 7 days with no activity. 21 | days-before-issue-close: "5" 22 | days-before-issue-stale: "180" 23 | days-before-pr-close: "-1" 24 | days-before-pr-stale: "45" 25 | operations-per-run: "2000" 26 | stale-issue-message: This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days. 27 | stale-pr-message: This PR is stale because it has been open 45 days with no activity. 28 | -------------------------------------------------------------------------------- /.conform.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2024-09-30T14:59:39Z by kres 8be5fa7. 4 | 5 | policies: 6 | - type: commit 7 | spec: 8 | dco: true 9 | gpg: 10 | required: true 11 | identity: 12 | gitHubOrganization: siderolabs 13 | spellcheck: 14 | locale: US 15 | maximumOfOneCommit: true 16 | header: 17 | length: 89 18 | imperative: true 19 | case: lower 20 | invalidLastCharacters: . 21 | body: 22 | required: true 23 | conventional: 24 | types: 25 | - chore 26 | - docs 27 | - perf 28 | - refactor 29 | - style 30 | - test 31 | - release 32 | scopes: 33 | - .* 34 | - type: license 35 | spec: 36 | root: . 37 | skipPaths: 38 | - .git/ 39 | - testdata/ 40 | includeSuffixes: 41 | - .go 42 | excludeSuffixes: 43 | - .pb.go 44 | - .pb.gw.go 45 | header: | 46 | // This Source Code Form is subject to the terms of the Mozilla Public 47 | // License, v. 2.0. If a copy of the MPL was not distributed with this 48 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 49 | -------------------------------------------------------------------------------- /hack/compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | omni-infra-provider-kubevirt: 4 | volumes: 5 | - state:/_out/state 6 | container_name: omni-infra-provider-kubevirt 7 | restart: on-failure 8 | cap_add: 9 | - NET_ADMIN 10 | build: 11 | context: ../../ 12 | dockerfile: Dockerfile 13 | args: 14 | - ARTIFACTS=${ARTIFACTS:?error} 15 | - SHA=${SHA:?error} 16 | - TAG=${TAG:?error} 17 | - USERNAME=${USERNAME:?error} 18 | - REGISTRY=${REGISTRY:?error} 19 | - NODE_BUILD_ARGS=${NODE_BUILD_ARGS} 20 | - TOOLCHAIN=${TOOLCHAIN:?error} 21 | - CGO_ENABLED=${CGO_ENABLED:?error} 22 | - GO_BUILDFLAGS=${GO_BUILDFLAGS} 23 | - GOLANGCILINT_VERSION=${GOLANGCILINT_VERSION:?error} 24 | - GOFUMPT_VERSION=${GOFUMPT_VERSION:?error} 25 | - GOIMPORTS_VERSION=${GOIMPORTS_VERSION:?error} 26 | - PROTOBUF_GO_VERSION=${PROTOBUF_GO_VERSION:?error} 27 | - GRPC_GO_VERSION=${GRPC_GO_VERSION:?error} 28 | - GRPC_GATEWAY_VERSION=${GRPC_GATEWAY_VERSION:?error} 29 | - VTPROTOBUF_VERSION=${VTPROTOBUF_VERSION:?error} 30 | - DEEPCOPY_VERSION=${DEEPCOPY_VERSION:?error} 31 | - TESTPKGS=${TESTPKGS:?error} 32 | - GO_LDFLAGS=${GO_LDFLAGS} 33 | 34 | volumes: 35 | state: 36 | -------------------------------------------------------------------------------- /hack/certs/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEVzCCAr+gAwIBAgIRAIfOe7RuXJAXhuacBA29W9EwDQYJKoZIhvcNAQELBQAw 3 | WTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMRcwFQYDVQQLDA51dGt1 4 | QHUtaG9tZS1wYzEeMBwGA1UEAwwVbWtjZXJ0IHV0a3VAdS1ob21lLXBjMB4XDTI0 5 | MDgxNjA4MTkwM1oXDTI2MTExNjA5MTkwM1owVjEnMCUGA1UEChMebWtjZXJ0IGRl 6 | dmVsb3BtZW50IGNlcnRpZmljYXRlMSswKQYDVQQLDCJ1dGt1QHUtd29yay1zaWRl 7 | cm8gKFV0a3Ugw5Z6ZGVtaXIpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 8 | AQEAuIpYRMvIy07EpmFvoU3pxa4fKrzWGGKaPT5EP6bHHeMMj4vdAcSj6ACAFkbE 9 | +RxN3JiYQ/HA7Qpcu/TeCTkh/Ky6FNTklEE7S+FPOJEPfqzaznsUfTvlEQUi8rt9 10 | /CkXZab1LNuc+2p/0h8H+gqjBsfqYKiKfurnMI2F704FsOejzoplX/7tV7OcbMv7 11 | Gh4UFM0MJaVQRhzrQcBVYoEM1KQrHny81BqVWXOSdhVUaEafpO+ophzm2V0KjHQC 12 | Ftg8yESellAeDB55CrDtuRHSx5UXRkva9AX/gl6jyenj2Cylw0QN/yki5Z3p0oR6 13 | dDUdg0DIYhuKA4uEm9U0GBZV6QIDAQABo4GcMIGZMA4GA1UdDwEB/wQEAwIFoDAT 14 | BgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBSUwQKJ6xTCiIbTU/iD3Wgy 15 | OE1oFjBRBgNVHREESjBIgglsb2NhbGhvc3SCCyoubG9jYWxob3N0ghVteS1pbnN0 16 | YW5jZS5sb2NhbGhvc3SCFyoubXktaW5zdGFuY2UubG9jYWxob3N0MA0GCSqGSIb3 17 | DQEBCwUAA4IBgQAcK6EcBER1ExJ+jaLRLvyvkw0Z9JhB5AVVpgKuE9XJiJHrQCuJ 18 | 4nFeCZ2Nse8VkPtLdUCzup9ycbBFGzEp6XzjoeBpvC+uTJ6AhjNG/vPhSzgwX++a 19 | 69BzLGZVvrsh1BOwVy676gif99E5s19slzYHFm4kq/cXhkE8zMww0gFa3Xb9FGJv 20 | hOfPA5yyJAC30bbUU0cKamGMRmS75jnWWlCrIwez+PEzEbLc7jELXfBtfX+zc8Ek 21 | IIpK4S/IgbXNM0dXVNHdhGE56hRB/kBZSjHNy7QSB/mPStInM9YSDz4HKYXCLhQ4 22 | NNXZYst3YFhmgJ8cuVAyP0AZ8gNtbzLhwZXW00UE0q8t+xpgEQ87v4vIqXLCwqOK 23 | iw+G5aGQpsZF6oHmPpPcQ5J7kHLIMvk+VVHVAivn4PRZqRkzbYxVennCcDqPStd4 24 | 5Y9cKB4iWIHjfmdwGOGKJEfLlUHpG7R/8NoXJ8Ga9NU0UvgpTXg4yn7ChV/Cj4H6 25 | hCLKZcW/DPjnWiI= 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /hack/certs/localhost-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC4ilhEy8jLTsSm 3 | YW+hTenFrh8qvNYYYpo9PkQ/pscd4wyPi90BxKPoAIAWRsT5HE3cmJhD8cDtCly7 4 | 9N4JOSH8rLoU1OSUQTtL4U84kQ9+rNrOexR9O+URBSLyu338KRdlpvUs25z7an/S 5 | Hwf6CqMGx+pgqIp+6ucwjYXvTgWw56POimVf/u1Xs5xsy/saHhQUzQwlpVBGHOtB 6 | wFVigQzUpCsefLzUGpVZc5J2FVRoRp+k76imHObZXQqMdAIW2DzIRJ6WUB4MHnkK 7 | sO25EdLHlRdGS9r0Bf+CXqPJ6ePYLKXDRA3/KSLlnenShHp0NR2DQMhiG4oDi4Sb 8 | 1TQYFlXpAgMBAAECggEBAKPnPD7eQJlSfJbKM7uw19EbtdLfpchCy3tZsoRWPMPu 9 | xVk5gDHx1SJaT2l5sbkPypgDcDnontHqQjMuaYcHl4g0YZHfBKYoyeG7XAGB1aFN 10 | JYn/B1OzvuA/D6tHm747QOyoPVp6NBOZo62cohkTGXkMVr9C8r+HI4+cIzlIswVL 11 | NW4+vCMZ9WQ5z98NpJX3isK6BDemWyfi702oTLG7XIwzn7GQWL0jQX+zOmYkmo+K 12 | InGSnrHl7pILs2InDIA/3AMI4K/w/mqu11h2+VKKmHUyOKi47lBUdtpZp9KLMA6W 13 | kJ3mwQX2RU8mAWpuGE+Bo23WApdcwRV+UYGtU+mE3YECgYEA0Q8OhvtF2/MWyLWp 14 | Q0hNJ4PK7+Htnx/xzxzEOadLwTio19cO51J83zlAqQ6dCE4HUsQmZVlMl7kq6zfL 15 | z7kn1x9H87YcBYnfxUFOQUKco5N/GibhJi85t0tjuReDU3GxZS7MsA7vsOn/uIdC 16 | W91FS01QxgAl1bEnCK2gbNWNYlsCgYEA4fnxDoRuprj83Jz4MxbLSpqOrQE+S1V2 17 | 3XGVHSo2x9i1d7T+CzVaug2r1Jqz02cRn15fE24B2KkoYz7eCNEJ7A0HfOLwwq2s 18 | m9RMyAFY/RoktIZb09SwYneleuX3pvIQJ7hkX0oxg7EeVK/1H93lCrgBz4SVeUXe 19 | nNzmkxY8FAsCgYEAt5MNIqJKudU/0IcUVqyKc4RbE0HEstION9v+wtGQx97FBKMn 20 | xyC73hgcG1dltQEvlRIA1UYQ57oFYf7gzUq9HT2upObovERRZpjt6ohfm5PNLF2v 21 | nyQg/j8JFmL7Qq63Iy5xNrgm6abQkmzTbG9khbcikntWvcqNiCVOlcMAH7kCgYEA 22 | pXg02JGGyNSKbC0Q3bAiOkXEldBkQhuZx3tlWg7QQDRiZP6GS8TM45IhMbP6W6GM 23 | WOtsqTiTZ4guR8YAJeqT3mKICh3PeG5eB1lEw+ugsu0S1ZHQ6eNDKUc9SCne10NH 24 | Kx6teM1GRo1KjW6vCp+cGOY2hTMrlLrh0HE88ZWFdpMCgYEAigbuLOfVlSbIQ8vg 25 | UJHf6JM5Lrc6oG6LW6fRUabnJibQ/TboNeV7PYd594swBrSwzJ/yRch8d6UIRVSB 26 | cftPlut2YvHcoMlOhqS0oOOFNJx1JFNj8s0SMfQBd7MXG8r+OSL4pWPL7EhVmsS2 27 | WMXSd3FqGMORF7NKqrtXGb203mk= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /internal/pkg/provider/resources/machine.go: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | // Package resources contains resources stored in the KubeVirt infra provider state. 6 | package resources 7 | 8 | import ( 9 | "github.com/cosi-project/runtime/pkg/resource" 10 | "github.com/cosi-project/runtime/pkg/resource/meta" 11 | "github.com/cosi-project/runtime/pkg/resource/protobuf" 12 | "github.com/cosi-project/runtime/pkg/resource/typed" 13 | "github.com/siderolabs/omni/client/pkg/infra" 14 | 15 | "github.com/siderolabs/omni-infra-provider-kubevirt/api/specs" 16 | providermeta "github.com/siderolabs/omni-infra-provider-kubevirt/internal/pkg/provider/meta" 17 | ) 18 | 19 | // NewMachine creates new Machine. 20 | func NewMachine(ns, id string) *Machine { 21 | return typed.NewResource[MachineSpec, MachineExtension]( 22 | resource.NewMetadata(ns, infra.ResourceType("Machine", providermeta.ProviderID), id, resource.VersionUndefined), 23 | protobuf.NewResourceSpec(&specs.MachineSpec{}), 24 | ) 25 | } 26 | 27 | // Machine describes fake machine configuration. 28 | type Machine = typed.Resource[MachineSpec, MachineExtension] 29 | 30 | // MachineSpec wraps specs.MachineSpec. 31 | type MachineSpec = protobuf.ResourceSpec[specs.MachineSpec, *specs.MachineSpec] 32 | 33 | // MachineExtension providers auxiliary methods for Machine resource. 34 | type MachineExtension struct{} 35 | 36 | // ResourceDefinition implements [typed.Extension] interface. 37 | func (MachineExtension) ResourceDefinition() meta.ResourceDefinitionSpec { 38 | return meta.ResourceDefinitionSpec{ 39 | Type: infra.ResourceType("Machine", providermeta.ProviderID), 40 | Aliases: []resource.Type{}, 41 | DefaultNamespace: infra.ResourceNamespace(providermeta.ProviderID), 42 | PrintColumns: []meta.PrintColumn{}, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Omni Infrastructure Provider for KubeVirt 2 | 3 | Can be used to automatically provision Talos nodes in a KubeVirt cluster. 4 | 5 | ## Running Infrastructure Provider 6 | 7 | First you need to create a service account for the infrastructure provider. 8 | 9 | ```bash 10 | $ omnictl serviceaccount create --role=InfraProvider --use-user-role=false infra-provider:kubevirt 11 | 12 | Set the following environment variables to use the service account: 13 | OMNI_ENDPOINT=https://.omni.siderolabs.io/ 14 | OMNI_SERVICE_ACCOUNT_KEY= 15 | 16 | Note: Store the service account key securely, it will not be displayed again 17 | ``` 18 | 19 | Create a service account kubeconfig for your KubeVirt cluster. 20 | Store it in `kubeconfig` file. 21 | 22 | If you are using `--data-volume-mode=Filesystem` (which is the default), make sure to enable the `ExpandDisks` featuregate in KubeVirt, e.g.: 23 | 24 | ```yaml 25 | apiVersion: kubevirt.io/v1 26 | kind: KubeVirt 27 | spec: 28 | configuration: 29 | developerConfiguration: 30 | featureGates: 31 | - ExpandDisks 32 | ``` 33 | 34 | By default VMs will use the bridge network binding mode. 35 | In IPv6 environments you might want to use [passt](https://kubevirt.io/user-guide/network/net_binding_plugins/passt/) instead. 36 | Make sure to set the provider configuration in your MachineClass accordingly. 37 | 38 | ### Using Docker 39 | 40 | ```bash 41 | docker run -it -d -v ./kubeconfig:/kubeconfig ghcr.io/siderolabs/omni-infra-provider-kubevirt --kubeconfig-file /kubeconfig --omni-api-endpoint https://.omni.siderolabs.io/ --omni-service-account-key 42 | ``` 43 | 44 | ### Using Executable 45 | 46 | Build the project (should have docker and buildx installed): 47 | 48 | ```bash 49 | make omni-infra-provider-linux-amd64 50 | ``` 51 | 52 | Run the executable: 53 | 54 | ```bash 55 | _out/omni-infra-provider-linux-amd64 --kubeconfig-file kubeconfig --omni-api-endpoint https://.omni.siderolabs.io/ --omni-service-account-key 56 | ``` 57 | -------------------------------------------------------------------------------- /hack/govulncheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Source: https://github.com/tianon/gosu/blob/e157efb/govulncheck-with-excludes.sh 3 | # Licensed under the Apache License, Version 2.0 4 | # Copyright Tianon Gravi 5 | set -Eeuo pipefail 6 | 7 | exclude_arg="" 8 | pass_args=() 9 | 10 | while [[ $# -gt 0 ]]; do 11 | case "$1" in 12 | -exclude) 13 | exclude_arg="$2" 14 | shift 2 15 | ;; 16 | *) 17 | pass_args+=("$1") 18 | shift 19 | ;; 20 | esac 21 | done 22 | 23 | if [[ -n "$exclude_arg" ]]; then 24 | excludeVulns="$(jq -nc --arg list "$exclude_arg" '$list | split(",")')" 25 | else 26 | excludeVulns="[]" 27 | fi 28 | 29 | export excludeVulns 30 | 31 | # Debug print 32 | echo "excludeVulns = $excludeVulns" 33 | echo "Passing args: ${pass_args[*]}" 34 | 35 | if ! command -v govulncheck > /dev/null; then 36 | printf "govulncheck not installed" 37 | exit 1 38 | fi 39 | 40 | if out="$(govulncheck "${pass_args[@]}")"; then 41 | printf '%s\n' "$out" 42 | exit 0 43 | fi 44 | 45 | json="$(govulncheck -json "${pass_args[@]}")" 46 | 47 | vulns="$(jq <<<"$json" -cs ' 48 | ( 49 | map( 50 | .osv // empty 51 | | { key: .id, value: . } 52 | ) 53 | | from_entries 54 | ) as $meta 55 | # https://github.com/tianon/gosu/issues/144 56 | | map( 57 | .finding // empty 58 | # https://github.com/golang/vuln/blob/3740f5cb12a3f93b18dbe200c4bcb6256f8586e2/internal/scan/template.go#L97-L104 59 | | select((.trace[0].function // "") != "") 60 | | .osv 61 | ) 62 | | unique 63 | | map($meta[.]) 64 | ')" 65 | if [ "$(jq <<<"$vulns" -r 'length')" -le 0 ]; then 66 | printf '%s\n' "$out" 67 | exit 1 68 | fi 69 | 70 | filtered="$(jq <<<"$vulns" -c ' 71 | (env.excludeVulns | fromjson) as $exclude 72 | | map(select( 73 | .id as $id 74 | | $exclude | index($id) | not 75 | )) 76 | ')" 77 | 78 | text="$(jq <<<"$filtered" -r 'map("- \(.id) (aka \(.aliases | join(", ")))\n\n\t\(.details | gsub("\n"; "\n\t"))") | join("\n\n")')" 79 | 80 | if [ -z "$text" ]; then 81 | printf 'No vulnerabilities found.\n' 82 | exit 0 83 | else 84 | printf '%s\n' "$text" 85 | exit 1 86 | fi 87 | -------------------------------------------------------------------------------- /hack/certs/key.public: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQINBGM1pZcBEADpbAWrOBHK3WDzwoxAgrzcoMEG6YSvKraBV/622SVeiwTfiz1Z 4 | Bij62jCTXoU0m+FpKXahbcTpcNoF8DFGkCJO6bY66a5IqccgezfZt/augByWju/6 5 | 9PJy9qCD5V//ASH+3Xh3gMyhnVOmkddAmfoGtgm8eE+bLTGW+2jQFh0blK0np5Ad 6 | ycWZJtKYWYrCV7KEUiaqfUgLFyyrc+ssIlqboLHHUtfsqZAUOYcSHv9DIvyVGNE8 7 | TOgir243KybNOUlbqmE+ubUQHKHOSWVAAP15XpgYPnZcJFlcBacbN+uY5SZ62sxl 8 | yNxrZ5wQepo+x5g9l8z9HbTKG7pVwgw4lz3r9msj5WRFhm/mqb123DB5yPwMZoI1 9 | hFTlE03Vma/kDZY0li8CCYE+kWTcy+GKt7biK74z83OUeTDeIwfLaj7VaRSDNelB 10 | xrooXMCrH2g8nSsFbkQ3mXjYnSYjTPXMAXeO8BFXMf68sjHsz49ychuY8A6QG7+8 11 | 4nbsV0761w/kUdOF7BtmKcx0usXxYfTPW1YsCYbI/I2QecYxL4fXK07JtZi+DPGv 12 | lQZvSSN8FUMER154ABSwA8CGYIZKHVGw8ugkGg+YCLkE/MfmyDkuFWgzvmiI5Yv3 13 | hqUcDVSbfyJPxORjPaOyDe/5uM8u4mjJ/p7HEbR72piCrAA/fCnB2Wyt2QARAQAB 14 | tChBbm90aGVyIEtleSA8YW5vdGhlcl9rZXlAc2lkZXJvbGFicy5jb20+iQJUBBMB 15 | CgA+FiEEWEqvBW4aEnjEeEUAjYzoQ1t0ggAFAmM1pZcCGwMFCQlmAYAFCwkIBwIG 16 | FQoJCAsCBBYCAwECHgECF4AACgkQjYzoQ1t0ggDDSw//SsVTfIGi6cHmdFOEolBS 17 | 7ewvcwCnY/HKeR3YPROFFvr5jdOyWY/dVJKY1x9MazDJx72NbErReEHZ6azxOrGL 18 | r7PDOLvChzQzqHZGncma5G69AcPehZJ8LW/OdCFK5j4gOCFb+KxvMpKjT7TiiWF0 19 | zSenJL78Tx9D9LdYy45ANnPFrprIkeq63GUnjbVUAeK2laaqp3Q7V7sALCh8uHyw 20 | hQUdg8/hhh2jyIARWP62+8FE6GfKGbiBAiw4ff5YhBzBL0NWB+9HrKHEAW+SEpGq 21 | 2zq1Y8oNEQIKEDMuXiwauT29b2o96COGo+N8+rTDGBVsDzBqLR4EwH/rsDZzz2xm 22 | HS3xCax4JWefIgLV3Cj8x/pxmH0UEiy9m5QRMbeVITgXBL6BnxboIE8fxzn9n9/q 23 | IZgemICLUUMWU6pR2rpCMN2u3YnNd7aPhKObUeo6QDN5Ya59IAruXYmkn/XNWSI3 24 | ySHpldxDE8NE+JUw5+JWfAS4AhTKIoXUcK/IEiF2ASbiACBVYdEZybfHOBQUQq6f 25 | NA7QLrZ5p0yW6TMeMeldgjN4ByFcKm9dTj9sy7pjW2LIzVDHKvV41CLiz57HhQS6 26 | yaIxVgT/MIFcS975sW/hK/pKFN979+Wl0pjV+/IUPZgjGb/g40DwLsqoKaRkBG73 27 | zUVmE/E9cMBA0h3pSMI8V265Ag0EYzWllwEQALmv4nDSosRnUumKHNi9XFKKFsDr 28 | 6DvDodzy0gho75CoaYOlvhu5pliIrt30fhMQw4dP+tSz9JgaK9CtroJ2BbKSgFAE 29 | 9LtMsnBtYE0+wp76xJBoGt68znGbnZ+lwfRkENe6ia6DhUUbpyjdg+Fks2EVLALP 30 | REmRTUVefsL8DfoPTjS5gPhO4pk1afUgz+5oumMnnSoKyFXo4G/1CkK+i2u07NTE 31 | A/AB/o3lOf3vkH1RGhKuz5s9rus2ADamX93Dr/TjpGFG2s08wYJC3Z/FeHcMTxLf 32 | hJSuVi2z9gIHJnyrxL/OUh5OXZBYy5g7czN35bzGaFUmbFNBxkWU/NUubloWtIIK 33 | JLuCQaTS2p6oz2A478HXkOVp9GUpff+y6CXdVvjeLqmNPJDYsQCJMUy7ed8yThYL 34 | EFhO7taUx6T+wXLyLxDpaKAUrE67WSuYCFy57K4aANkz5vwJUBsx5KDLrLDyCWd8 35 | UYS/CtMl8k7wHWl01VwFq9jx5YspVgo9k9eFWTC9ARS5c5Olmcz224BaR87lBQmj 36 | gLbX7DKhRMZe9ickwHoB3vDVuW0c9Mv9hu+1lcXMyoV56T4oHHQl7D+Fk/m786RD 37 | dL3U0V01qjr4cWK5WKemX16atnROAEcgWbSqBoJKUo7dRnQKeqBFJK/3fXc0PZcP 38 | VB3cotiL9lOEcJv1ABEBAAGJAjwEGAEKACYWIQRYSq8FbhoSeMR4RQCNjOhDW3SC 39 | AAUCYzWllwIbDAUJCWYBgAAKCRCNjOhDW3SCAAEDEADIJn1yuKkg5E2qy2T28bWP 40 | VJ8DwpmmKntfRIasb7nBcc4iKQGvbYF9i6OV6LMxExeiq4W1vj87/WMsmCxBWf7U 41 | +KVUEaelARBBq9y0vgmL/El35VRCZRSsNXgnQbVK7ZFHC45GFZTRpMQPcx6ejPZt 42 | demrRTzFNehF1SQ80Fn3U0n0f7sOmuFJ7lF4ahi5pfsgyLSNCIWlOMnxnnzYD4lT 43 | xfwpoPKWhPoHcvgacspsYxm1eunAG0ElFCn4fLrlEBT3jyJO9PJ/d+mA2RRm6H39 44 | E8xRYzx+1Rupq1KKkvqU/S+he/NFKvitc7mWhoQ4OA5n5F5ENq9Cf4g57ePGouIM 45 | Cu4u7K9VMzFW6EfnzMW5a8fPfIJp7V5fxE0r3/TBXuTCQEba0tGF4wxxgtB5pqx5 46 | jSMf9Vf9RoJW/HNaYzStTJNUcdPDoJxWqyVhbr3GCCDqV9OX6No+NJONr54wkLk4 47 | gmgX/lmai2A73SD9L8XF4D0KXOfIk+8t/Y2vQK+nystfkZX6pQ8fPasy4zIuZrJo 48 | cQDB4tixns/QrPCr+Zf4PLVX1HlmQScvn+uaLUMAFTf6LozTYlHYW8y+HaVc6Qre 49 | +Fbh0SKHcowXBN5PSq5yF3ElI6utDgrAwmNamVoPTQiA60jtKKY9hFM91KE2HGMs 50 | 2lEebIgAF9oRsC9BU9vSsg== 51 | =f37X 52 | -----END PGP PUBLIC KEY BLOCK----- 53 | -------------------------------------------------------------------------------- /cmd/omni-infra-provider-kubevirt/data/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.github/workflows/slack-notify-ci-failure.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-11-06T14:58:30Z by kres 4ba9b0c. 4 | 5 | "on": 6 | workflow_run: 7 | workflows: 8 | - default 9 | types: 10 | - completed 11 | branches: 12 | - main 13 | name: slack-notify-failure 14 | jobs: 15 | slack-notify: 16 | runs-on: 17 | group: generic 18 | if: github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event != 'pull_request' 19 | steps: 20 | - name: Slack Notify 21 | uses: slackapi/slack-github-action@v2 22 | with: 23 | method: chat.postMessage 24 | payload: | 25 | { 26 | "channel": "ci-failure", 27 | "text": "${{ github.event.workflow_run.conclusion }} - ${{ github.repository }}", 28 | "icon_emoji": "${{ github.event.workflow_run.conclusion == 'success' && ':white_check_mark:' || github.event.workflow_run.conclusion == 'failure' && ':x:' || ':warning:' }}", 29 | "username": "GitHub Actions", 30 | "attachments": [ 31 | { 32 | "blocks": [ 33 | { 34 | "fields": [ 35 | { 36 | "text": "${{ github.event.workflow_run.event == 'pull_request' && format('*Pull Request:* {0} (`{1}`)\n<{2}/pull/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, steps.get-pr-number.outputs.pull_request_number, github.event.workflow_run.display_title) || format('*Build:* {0} (`{1}`)\n<{2}/commit/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, github.sha, github.event.workflow_run.display_title) }}", 37 | "type": "mrkdwn" 38 | }, 39 | { 40 | "text": "*Status:*\n`${{ github.event.workflow_run.conclusion }}`", 41 | "type": "mrkdwn" 42 | } 43 | ], 44 | "type": "section" 45 | }, 46 | { 47 | "fields": [ 48 | { 49 | "text": "*Author:*\n`${{ github.actor }}`", 50 | "type": "mrkdwn" 51 | }, 52 | { 53 | "text": "*Event:*\n`${{ github.event.workflow_run.event }}`", 54 | "type": "mrkdwn" 55 | } 56 | ], 57 | "type": "section" 58 | }, 59 | { 60 | "type": "divider" 61 | }, 62 | { 63 | "elements": [ 64 | { 65 | "text": { 66 | "text": "Logs", 67 | "type": "plain_text" 68 | }, 69 | "type": "button", 70 | "url": "${{ github.event.workflow_run.html_url }}" 71 | }, 72 | { 73 | "text": { 74 | "text": "Commit", 75 | "type": "plain_text" 76 | }, 77 | "type": "button", 78 | "url": "${{ github.event.repository.html_url }}/commit/${{ github.sha }}" 79 | } 80 | ], 81 | "type": "actions" 82 | } 83 | ], 84 | "color": "${{ github.event.workflow_run.conclusion == 'success' && '#2EB886' || github.event.workflow_run.conclusion == 'failure' && '#A30002' || '#FFCC00' }}" 85 | } 86 | ] 87 | } 88 | token: ${{ secrets.SLACK_BOT_TOKEN_V2 }} 89 | -------------------------------------------------------------------------------- /hack/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 4 | # 5 | # Generated on 2024-09-02T11:17:15Z by kres b5ca957. 6 | 7 | set -e 8 | 9 | RELEASE_TOOL_IMAGE="ghcr.io/siderolabs/release-tool:latest" 10 | 11 | function release-tool { 12 | docker pull "${RELEASE_TOOL_IMAGE}" >/dev/null 13 | docker run --rm -w /src -v "${PWD}":/src:ro "${RELEASE_TOOL_IMAGE}" -l -d -n -t "${1}" ./hack/release.toml 14 | } 15 | 16 | function changelog { 17 | if [ "$#" -eq 1 ]; then 18 | (release-tool ${1}; echo; cat CHANGELOG.md) > CHANGELOG.md- && mv CHANGELOG.md- CHANGELOG.md 19 | else 20 | echo 1>&2 "Usage: $0 changelog [tag]" 21 | exit 1 22 | fi 23 | } 24 | 25 | function release-notes { 26 | release-tool "${2}" > "${1}" 27 | } 28 | 29 | function cherry-pick { 30 | if [ $# -ne 2 ]; then 31 | echo 1>&2 "Usage: $0 cherry-pick " 32 | exit 1 33 | fi 34 | 35 | git checkout $2 36 | git fetch 37 | git rebase upstream/$2 38 | git cherry-pick -x $1 39 | } 40 | 41 | function commit { 42 | if [ $# -ne 1 ]; then 43 | echo 1>&2 "Usage: $0 commit " 44 | exit 1 45 | fi 46 | 47 | if is_on_main_branch; then 48 | update_license_files 49 | fi 50 | 51 | git commit -s -m "release($1): prepare release" -m "This is the official $1 release." 52 | } 53 | 54 | function is_on_main_branch { 55 | main_remotes=("upstream" "origin") 56 | branch_names=("main" "master") 57 | current_branch=$(git rev-parse --abbrev-ref HEAD) 58 | 59 | echo "Check current branch: $current_branch" 60 | 61 | for remote in "${main_remotes[@]}"; do 62 | echo "Fetch remote $remote..." 63 | 64 | if ! git fetch --quiet "$remote" &>/dev/null; then 65 | echo "Failed to fetch $remote, skip..." 66 | 67 | continue 68 | fi 69 | 70 | for branch_name in "${branch_names[@]}"; do 71 | if ! git rev-parse --verify "$branch_name" &>/dev/null; then 72 | echo "Branch $branch_name does not exist, skip..." 73 | 74 | continue 75 | fi 76 | 77 | echo "Branch $remote/$branch_name exists, comparing..." 78 | 79 | merge_base=$(git merge-base "$current_branch" "$remote/$branch_name") 80 | latest_main=$(git rev-parse "$remote/$branch_name") 81 | 82 | if [ "$merge_base" = "$latest_main" ]; then 83 | echo "Current branch is up-to-date with $remote/$branch_name" 84 | 85 | return 0 86 | else 87 | echo "Current branch is not on $remote/$branch_name" 88 | 89 | return 1 90 | fi 91 | done 92 | done 93 | 94 | echo "No main or master branch found on any remote" 95 | 96 | return 1 97 | } 98 | 99 | function update_license_files { 100 | script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 101 | parent_dir="$(dirname "$script_dir")" 102 | current_year=$(date +"%Y") 103 | change_date=$(date -v+4y +"%Y-%m-%d" 2>/dev/null || date -d "+4 years" +"%Y-%m-%d" 2>/dev/null || date --date="+4 years" +"%Y-%m-%d") 104 | 105 | # Find LICENSE and .kres.yaml files recursively in the parent directory (project root) 106 | find "$parent_dir" \( -name "LICENSE" -o -name ".kres.yaml" \) -type f | while read -r file; do 107 | temp_file="${file}.tmp" 108 | 109 | if [[ $file == *"LICENSE" ]]; then 110 | if grep -q "^Business Source License" "$file"; then 111 | sed -e "s/The Licensed Work is (c) [0-9]\{4\}/The Licensed Work is (c) $current_year/" \ 112 | -e "s/Change Date: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/Change Date: $change_date/" \ 113 | "$file" >"$temp_file" 114 | else 115 | continue # Not a Business Source License file 116 | fi 117 | elif [[ $file == *".kres.yaml" ]]; then 118 | sed -E 's/^([[:space:]]*)ChangeDate:.*$/\1ChangeDate: "'"$change_date"'"/' "$file" >"$temp_file" 119 | fi 120 | 121 | # Check if the file has changed 122 | if ! cmp -s "$file" "$temp_file"; then 123 | mv "$temp_file" "$file" 124 | echo "Updated: $file" 125 | git add "$file" 126 | else 127 | echo "No changes: $file" 128 | rm "$temp_file" 129 | fi 130 | done 131 | } 132 | 133 | if declare -f "$1" > /dev/null 134 | then 135 | cmd="$1" 136 | shift 137 | $cmd "$@" 138 | else 139 | cat <- 42 | ARTIFACTS="$(ARTIFACTS)" 43 | SHA="$(SHA)" 44 | TAG="$(TAG)" 45 | USERNAME="$(USERNAME)" 46 | REGISTRY="$(REGISTRY)" 47 | PROTOBUF_TS_VERSION="$(PROTOBUF_TS_VERSION)" 48 | NODE_BUILD_ARGS="$(NODE_BUILD_ARGS)" 49 | TOOLCHAIN="$(TOOLCHAIN)" 50 | CGO_ENABLED="$(CGO_ENABLED)" 51 | GO_BUILDFLAGS="$(GO_BUILDFLAGS)" 52 | GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)" 53 | GOFUMPT_VERSION="$(GOFUMPT_VERSION)" 54 | GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)" 55 | PROTOBUF_GO_VERSION="$(PROTOBUF_GO_VERSION)" 56 | GRPC_GO_VERSION="$(GRPC_GO_VERSION)" 57 | GRPC_GATEWAY_VERSION="$(GRPC_GATEWAY_VERSION)" 58 | VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)" 59 | DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)" 60 | TESTPKGS="$(TESTPKGS)" 61 | COMPOSE_DOCKER_CLI_BUILD=1 62 | DOCKER_BUILDKIT=1 63 | GO_LDFLAGS="$(GO_LDFLAGS)" 64 | docker compose -p talemu --file ./hack/compose/docker-compose.yml --file ./hack/compose/docker-compose.override.yml up --build 65 | --- 66 | kind: custom.Step 67 | name: docker-compose-down 68 | spec: 69 | makefile: 70 | enabled: true 71 | phony: true 72 | variables: 73 | - name: REMOVE_VOLUMES 74 | defaultValue: false 75 | script: 76 | - >- 77 | ARTIFACTS="$(ARTIFACTS)" 78 | SHA="$(SHA)" 79 | TAG="$(TAG)" 80 | USERNAME="$(USERNAME)" 81 | REGISTRY="$(REGISTRY)" 82 | PROTOBUF_TS_VERSION="$(PROTOBUF_TS_VERSION)" 83 | NODE_BUILD_ARGS="$(NODE_BUILD_ARGS)" 84 | TOOLCHAIN="$(TOOLCHAIN)" 85 | CGO_ENABLED="$(CGO_ENABLED)" 86 | GO_BUILDFLAGS="$(GO_BUILDFLAGS)" 87 | GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)" 88 | GOFUMPT_VERSION="$(GOFUMPT_VERSION)" 89 | GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)" 90 | PROTOBUF_GO_VERSION="$(PROTOBUF_GO_VERSION)" 91 | GRPC_GO_VERSION="$(GRPC_GO_VERSION)" 92 | GRPC_GATEWAY_VERSION="$(GRPC_GATEWAY_VERSION)" 93 | VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)" 94 | DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)" 95 | TESTPKGS="$(TESTPKGS)" 96 | COMPOSE_DOCKER_CLI_BUILD=1 97 | DOCKER_BUILDKIT=1 98 | GO_LDFLAGS="$(GO_LDFLAGS)" 99 | docker compose -p talemu --file ./hack/compose/docker-compose.yml --file ./hack/compose/docker-compose.override.yml down --rmi local --remove-orphans --volumes=$(REMOVE_VOLUMES) 100 | --- 101 | kind: custom.Step 102 | name: run-integration-test 103 | spec: 104 | sudoInCI: true 105 | makefile: 106 | enabled: true 107 | depends: 108 | - omni-infra-provider-kubevirt 109 | script: 110 | - >- 111 | @hack/test/integration.sh 112 | ghaction: 113 | enabled: true 114 | sops: true 115 | artifacts: 116 | enabled: true 117 | extraPaths: 118 | - "!_out/omni/" 119 | additional: 120 | - name: talos-logs 121 | always: true 122 | continueOnError: true 123 | paths: 124 | - "~/.talos/clusters/**/*.log" 125 | - "!~/.talos/clusters/**/swtpm.log" 126 | - name: omni-logs 127 | always: true 128 | continueOnError: true 129 | paths: 130 | - "/tmp/kubevirt-e2e/*.log" 131 | --- 132 | kind: common.SOPS 133 | spec: 134 | enabled: true 135 | config: |- 136 | creation_rules: 137 | - age: age1xrpa9ujxxcj2u2gzfrzv8mxak4rts94a6y60ypurv6rs5cpr4e4sg95f0k 138 | # order: Andrey, Noel, Artem, Utku, Dmitriy 139 | pgp: >- 140 | 15D5721F5F5BAF121495363EFE042E3D4085A811, 141 | CC51116A94490FA6FB3C18EB2401FCAE863A06CA, 142 | 4919F560F0D35F80CF382D76E084A2DF1143C14D, 143 | 966BC282A680D8BB3E8363E865933E76F0549B0D, 144 | AA5213AF261C1977AF38B03A94B473337258BFD5 145 | -------------------------------------------------------------------------------- /.secrets.yaml: -------------------------------------------------------------------------------- 1 | secrets: 2 | AUTH0_TEST_USERNAME: ENC[AES256_GCM,data:lPddHbDVfWxaEW7ujLDnWdhIBMFj2hcp,iv:oG3Ebn8ym7g/Z7L3A3BTHRHIk+zzblZKvzMKYMPSfWI=,tag:wV7xJWbnLrj/UWj0fGGQCw==,type:str] 3 | AUTH0_TEST_PASSWORD: ENC[AES256_GCM,data:3tgQjqv5ktdnnGUQw5Lpuw==,iv:F8zYxqk5P0tV1Pvt6QBlho8H0wuX+K91pgwLzF+4kC8=,tag:HJ4s14d/u2KyP780wFDk/w==,type:str] 4 | AUTH0_CLIENT_ID: ENC[AES256_GCM,data:HevA8uFKCOPF8W/FRjSo/pyUFN66eXwvAxaqT5LdnT0=,iv:qpWNjsRSZ28lWQJGfMoGQvLY8KRKWv1dhR07vCgIvIU=,tag:x5BS26iacdBMv2ZkdCdr3A==,type:str] 5 | AUTH0_DOMAIN: ENC[AES256_GCM,data:2vv9ay+hC1kN46MG8E0v1Z3G7Dm0hMmLx1/AWg==,iv:9thZflFQ1yhf0jH3u6Om7RV7Y/qYzrTf82hoYrDvyG0=,tag:BUNuHJobt/NoR5FFQBIbIQ==,type:str] 6 | sops: 7 | kms: [] 8 | gcp_kms: [] 9 | azure_kv: [] 10 | hc_vault: [] 11 | age: 12 | - recipient: age1xrpa9ujxxcj2u2gzfrzv8mxak4rts94a6y60ypurv6rs5cpr4e4sg95f0k 13 | enc: | 14 | -----BEGIN AGE ENCRYPTED FILE----- 15 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrUExvc1oyUzdVNmgrbHh3 16 | cDllQ2VGSzZLQWV5MkN0VU1qTjVqblFvekJZCkdyREg2RUhVSXQwM1lpcjBkb0dG 17 | b0krdTI1MVQxcE4zSElsd0liS0xrYncKLS0tIG1nSmhVa2Z1YkhjdHpnQmg5b1lL 18 | NXI3VkxLU0htQUZ0Ry8rYUpLTnNXYlkKzfLUus7SkKBEj+oG3f7NBe+6UVidpxRd 19 | OvOSqsACIUJJnRdfs8/X5Jbvruz38Zt3dYR436NFo2IHtYUdHIHO3Q== 20 | -----END AGE ENCRYPTED FILE----- 21 | lastmodified: "2024-05-06T09:52:57Z" 22 | mac: ENC[AES256_GCM,data:4qmhG/liKJdnEBxvvnxnpb9xJpS8GGjCAHGUVM4dGtYY5+TkfgnSQyvVdg88Ag16nMDTBEeRJO6VfOYD/Wx/PfIYnajhxRm3ZYuPPSJ5t0LGqRryUtR9vJTtHuTew5gjX8FCTvjiGJzqcfTiq11HhN3Xyu7VNwwan50QUvz5oKY=,iv:Rc0/1kH74ahBkNygwFrOZymWMnPj3VCQZ7wBi1d7Rzc=,tag:Cgdjhlc24S2gklSKYe5mPw==,type:str] 23 | pgp: 24 | - created_at: "2024-04-18T18:21:00Z" 25 | enc: |- 26 | -----BEGIN PGP MESSAGE----- 27 | 28 | hF4D/dYBJRlWfQISAQdAVAV7d4BdulmFD+opnoDgxoIcDlIGn2n7c2aWbeF1qjYw 29 | eHfSb/A/1Anwi+uA7fXAqAayhlfTFTr9xdKr9zp+rDQt09/QN9EKG2F9gBq0LPCl 30 | 0lwBAxelOP0EUjXZtpsVk8FVZcBeuYt+U+DrAVr8yT3TUiyFvavzpxxCqUYFBjvy 31 | z5DUSCs+YUDLpQ/Gde0qBW8LU6HO2LAGkIvfO/HAd35jVHT5EvXivMlaRb+qBg== 32 | =hdU9 33 | -----END PGP MESSAGE----- 34 | fp: 15D5721F5F5BAF121495363EFE042E3D4085A811 35 | - created_at: "2024-04-18T18:21:00Z" 36 | enc: |- 37 | -----BEGIN PGP MESSAGE----- 38 | 39 | hF4D+EORkHurkvgSAQdAOxZd1WYD0pC25Y7bBmPhlz9+udxy+RiwaxL2RXs2/xYw 40 | cIvqsTY4wokWKD3s1nFmqHDXU3GQ7+V+pCS1PXTs7YH3uwXLBaT86AUgp+JoLJmN 41 | 0lwBuFrV4rSBQ5NvY1lGmOz6zaZlf3oBvVX510bvLPG6RfUqxE5WkMl+XgYtoKNa 42 | eK2uknJ5UhMKYJpYwi0Jcj6Ip3s0Bzt2ZR4SMYvw7QzXPvJ1W3GKboOjJAxqoQ== 43 | =YydP 44 | -----END PGP MESSAGE----- 45 | fp: CC51116A94490FA6FB3C18EB2401FCAE863A06CA 46 | - created_at: "2024-04-18T18:21:00Z" 47 | enc: |- 48 | -----BEGIN PGP MESSAGE----- 49 | 50 | hF4DCsA/BhMt3V4SAQdAtLfcBQyS/chcBtMAz6cJ/q/jZihioun7AZssYBzGdFIw 51 | jwXCKTbTFAG7ebentk4dDLYWxRRwY/lHsWyAS1kDSSfQVZNfK+ZoTrGIG1J6MYDD 52 | 0lwBazJw7Xh+MBXt9nz/Pdor4Jlnerl1PvO3BsDvql5ESbWZS/OOSFGTvuq9ZUG0 53 | RRlvN38NSNz+R1D79U+iwsJDJ7s8qUPCNckAoU3RWkqa7Sv1rpnwLPBqZ4t6bA== 54 | =JQty 55 | -----END PGP MESSAGE----- 56 | fp: 4919F560F0D35F80CF382D76E084A2DF1143C14D 57 | - created_at: "2024-04-18T18:21:00Z" 58 | enc: |- 59 | -----BEGIN PGP MESSAGE----- 60 | 61 | hQEMAxQwM84t19oOAQf/TQnaKyseOPFTpIMXoZAHsJ71jVGTdevAhOK9Vrq4ULwk 62 | Mb/QIyjLssrxBKU2AeXPXHM3SfiboqRsfoUKLuTmBI+BZyq6xXSA5HPElS+VcodE 63 | sLTce4en+YeWvcJ5vioNCqj0P6GTEdZfB5bXRzhJArQMyyEGvAaQG/5SKI8lJ4gW 64 | q0jXhwWy3qZRGj+X35y+vjlorwIEjPDrrh3lddnt+I1uVO2SKO4irbO3OiLAHRUM 65 | bTyeIdqsVJN9tWdlotPIA5+IQK+Bd+G6Tu4rGnKxsEo2wTfomcR99HTBLYIVkVSm 66 | iswaGDffJ3DAIWEBUDdOZD1zOOAb0xESkkEfIbfcxdJcAesPBVc/jkL9cd17oHCU 67 | sSEDeQnkFcwwfa3Lvo91CqrXx/I9Np/D6Ir/BsdYl4IUrcOtpYjVRQh3V9MfXpuY 68 | RST6NbjIziAMOPbJaxXKOZbT+inksnFvblo39HE= 69 | =5g11 70 | -----END PGP MESSAGE----- 71 | fp: 966BC282A680D8BB3E8363E865933E76F0549B0D 72 | - created_at: "2024-04-18T18:21:00Z" 73 | enc: |- 74 | -----BEGIN PGP MESSAGE----- 75 | 76 | hF4DzfZC0UNQ1VgSAQdABhWHHlBVw7gq430dMuRHIzJ4u6f5oVh8jXBbMGG8tXow 77 | lBUy2Qo9sGgN/2Nu9/W+efxs31oceerrw4DMSalC/KWvq3teVWc8TYeHYNAd/4ci 78 | 0lwB/UsGhZio7njWdmt7chOHJgM76JUEb4eaEZCVhQCCBDTIaFffMF2b0gpgyG9p 79 | orZob5tXAl1RsYS9ZDAlGWpuicfZ8CUxQvdSKzwBzBrBJhs+CvNVk/NFWXNS3Q== 80 | =N/JL 81 | -----END PGP MESSAGE----- 82 | fp: AA5213AF261C1977AF38B03A94B473337258BFD5 83 | unencrypted_suffix: _unencrypted 84 | version: 3.8.1 85 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-07-24T12:03:40Z by kres 4c6b4c0. 4 | 5 | version: "2" 6 | 7 | # options for analysis running 8 | run: 9 | modules-download-mode: readonly 10 | issues-exit-code: 1 11 | tests: true 12 | 13 | # output configuration options 14 | output: 15 | formats: 16 | text: 17 | path: stdout 18 | print-issued-lines: true 19 | print-linter-name: true 20 | path-prefix: "" 21 | 22 | 23 | linters: 24 | default: all 25 | disable: 26 | - exhaustruct 27 | - err113 28 | - forbidigo 29 | - funcorder 30 | - funlen 31 | - gochecknoglobals 32 | - gochecknoinits 33 | - godox 34 | - gomoddirectives 35 | - gosec 36 | - inamedparam 37 | - ireturn 38 | - mnd 39 | - nestif 40 | - nonamedreturns 41 | - paralleltest 42 | - tagalign 43 | - tagliatelle 44 | - thelper 45 | - varnamelen 46 | - wrapcheck 47 | - testifylint # complains about our assert recorder and has a number of false positives for assert.Greater(t, thing, 1) 48 | - protogetter # complains about us using Value field on typed spec, instead of GetValue which has a different signature 49 | - perfsprint # complains about us using fmt.Sprintf in non-performance critical code, updating just kres took too long 50 | - musttag # seems to be broken - goes into imported libraries and reports issues there 51 | - nolintlint # gives false positives - disable until https://github.com/golangci/golangci-lint/issues/3228 is resolved 52 | - wsl # replaced by wsl_v5 53 | - noinlineerr 54 | - embeddedstructfieldcheck # fighting in many places with fieldalignment 55 | # all available settings of specific linters 56 | settings: 57 | cyclop: 58 | # the maximal code complexity to report 59 | max-complexity: 20 60 | dogsled: 61 | max-blank-identifiers: 2 62 | dupl: 63 | threshold: 150 64 | errcheck: 65 | check-type-assertions: true 66 | check-blank: true 67 | exhaustive: 68 | default-signifies-exhaustive: false 69 | gocognit: 70 | min-complexity: 30 71 | nestif: 72 | min-complexity: 5 73 | goconst: 74 | min-len: 3 75 | min-occurrences: 3 76 | gocritic: 77 | disabled-checks: [ ] 78 | gocyclo: 79 | min-complexity: 20 80 | godot: 81 | scope: declarations 82 | gomodguard: { } 83 | govet: 84 | enable-all: true 85 | lll: 86 | line-length: 200 87 | tab-width: 4 88 | misspell: 89 | locale: US 90 | nakedret: 91 | max-func-lines: 30 92 | prealloc: 93 | simple: true 94 | range-loops: true # Report preallocation suggestions on range loops, true by default 95 | for-loops: false # Report preallocation suggestions on for loops, false by default 96 | revive: 97 | rules: 98 | - name: var-naming # Complains about package names like "common" 99 | disabled: true 100 | rowserrcheck: { } 101 | testpackage: { } 102 | unparam: 103 | check-exported: false 104 | unused: 105 | local-variables-are-used: false 106 | whitespace: 107 | multi-if: false # Enforces newlines (or comments) after every multi-line if statement 108 | multi-func: false # Enforces newlines (or comments) after every multi-line function signature 109 | wsl: 110 | strict-append: true 111 | allow-assign-and-call: true 112 | allow-multiline-assign: true 113 | allow-trailing-comment: false 114 | force-case-trailing-whitespace: 0 115 | allow-separated-leading-comment: false 116 | allow-cuddle-declarations: false 117 | force-err-cuddling: false 118 | depguard: 119 | rules: 120 | prevent_unmaintained_packages: 121 | list-mode: lax # allow unless explicitly denied 122 | files: 123 | - $all 124 | deny: 125 | - pkg: io/ioutil 126 | desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil" 127 | 128 | exclusions: 129 | generated: lax 130 | paths: 131 | - third_party$ 132 | - builtin$ 133 | - examples$ 134 | issues: 135 | max-issues-per-linter: 10 136 | max-same-issues: 3 137 | uniq-by-line: true 138 | new: false 139 | 140 | severity: 141 | default: error 142 | formatters: 143 | enable: 144 | - gci 145 | - gofmt 146 | - gofumpt 147 | settings: 148 | gci: 149 | sections: 150 | - standard 151 | - default 152 | - localmodule 153 | gofmt: 154 | simplify: true 155 | gofumpt: 156 | extra-rules: false 157 | exclusions: 158 | generated: lax 159 | paths: 160 | - third_party$ 161 | - builtin$ 162 | - examples$ 163 | -------------------------------------------------------------------------------- /.github/workflows/slack-notify.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-11-06T14:58:30Z by kres 4ba9b0c. 4 | 5 | "on": 6 | workflow_run: 7 | workflows: 8 | - default 9 | types: 10 | - completed 11 | name: slack-notify 12 | jobs: 13 | slack-notify: 14 | runs-on: 15 | group: generic 16 | if: github.event.workflow_run.conclusion != 'skipped' 17 | steps: 18 | - name: Get PR number 19 | id: get-pr-number 20 | if: github.event.workflow_run.event == 'pull_request' 21 | env: 22 | GH_TOKEN: ${{ github.token }} 23 | run: | 24 | echo pull_request_number=$(gh pr view -R ${{ github.repository }} ${{ github.event.workflow_run.head_repository.owner.login }}:${{ github.event.workflow_run.head_branch }} --json number --jq .number) >> $GITHUB_OUTPUT 25 | - name: Slack Notify 26 | uses: slackapi/slack-github-action@v2 27 | with: 28 | method: chat.postMessage 29 | payload: | 30 | { 31 | "channel": "ci-all", 32 | "text": "${{ github.event.workflow_run.conclusion }} - ${{ github.repository }}", 33 | "icon_emoji": "${{ github.event.workflow_run.conclusion == 'success' && ':white_check_mark:' || github.event.workflow_run.conclusion == 'failure' && ':x:' || ':warning:' }}", 34 | "username": "GitHub Actions", 35 | "attachments": [ 36 | { 37 | "blocks": [ 38 | { 39 | "fields": [ 40 | { 41 | "text": "${{ github.event.workflow_run.event == 'pull_request' && format('*Pull Request:* {0} (`{1}`)\n<{2}/pull/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, steps.get-pr-number.outputs.pull_request_number, github.event.workflow_run.display_title) || format('*Build:* {0} (`{1}`)\n<{2}/commit/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, github.sha, github.event.workflow_run.display_title) }}", 42 | "type": "mrkdwn" 43 | }, 44 | { 45 | "text": "*Status:*\n`${{ github.event.workflow_run.conclusion }}`", 46 | "type": "mrkdwn" 47 | } 48 | ], 49 | "type": "section" 50 | }, 51 | { 52 | "fields": [ 53 | { 54 | "text": "*Author:*\n`${{ github.actor }}`", 55 | "type": "mrkdwn" 56 | }, 57 | { 58 | "text": "*Event:*\n`${{ github.event.workflow_run.event }}`", 59 | "type": "mrkdwn" 60 | } 61 | ], 62 | "type": "section" 63 | }, 64 | { 65 | "type": "divider" 66 | }, 67 | { 68 | "elements": [ 69 | { 70 | "text": { 71 | "text": "Logs", 72 | "type": "plain_text" 73 | }, 74 | "type": "button", 75 | "url": "${{ github.event.workflow_run.html_url }}" 76 | }, 77 | { 78 | "text": { 79 | "text": "Commit", 80 | "type": "plain_text" 81 | }, 82 | "type": "button", 83 | "url": "${{ github.event.repository.html_url }}/commit/${{ github.sha }}" 84 | } 85 | ], 86 | "type": "actions" 87 | } 88 | ], 89 | "color": "${{ github.event.workflow_run.conclusion == 'success' && '#2EB886' || github.event.workflow_run.conclusion == 'failure' && '#A30002' || '#FFCC00' }}" 90 | } 91 | ] 92 | } 93 | token: ${{ secrets.SLACK_BOT_TOKEN_V2 }} 94 | -------------------------------------------------------------------------------- /cmd/omni-infra-provider-kubevirt/main.go: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | // Package main is the root cmd of the provider script. 6 | package main 7 | 8 | import ( 9 | "context" 10 | _ "embed" 11 | "encoding/base64" 12 | "fmt" 13 | "os" 14 | "os/signal" 15 | "slices" 16 | "syscall" 17 | 18 | "github.com/go-logr/logr" 19 | "github.com/siderolabs/omni/client/pkg/client" 20 | "github.com/siderolabs/omni/client/pkg/infra" 21 | "github.com/spf13/cobra" 22 | "go.uber.org/zap" 23 | "go.uber.org/zap/zapcore" 24 | v1 "k8s.io/api/core/v1" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/client-go/tools/clientcmd" 27 | kvv1 "kubevirt.io/api/core/v1" 28 | cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" 29 | k8sclient "sigs.k8s.io/controller-runtime/pkg/client" 30 | "sigs.k8s.io/controller-runtime/pkg/log" 31 | 32 | "github.com/siderolabs/omni-infra-provider-kubevirt/internal/pkg/provider" 33 | "github.com/siderolabs/omni-infra-provider-kubevirt/internal/pkg/provider/data" 34 | "github.com/siderolabs/omni-infra-provider-kubevirt/internal/pkg/provider/meta" 35 | ) 36 | 37 | //go:embed data/icon.svg 38 | var icon []byte 39 | 40 | // rootCmd represents the base command when called without any subcommands. 41 | var rootCmd = &cobra.Command{ 42 | Use: "provider", 43 | Short: "KubeVirt Omni infrastructure provider", 44 | Long: `Connects to Omni as an infra provider and manages VMs in KubeVirt`, 45 | SilenceUsage: true, 46 | RunE: func(cmd *cobra.Command, _ []string) error { 47 | loggerConfig := zap.NewProductionConfig() 48 | 49 | logger, err := loggerConfig.Build( 50 | zap.AddStacktrace(zapcore.ErrorLevel), 51 | ) 52 | if err != nil { 53 | return fmt.Errorf("failed to create logger: %w", err) 54 | } 55 | 56 | log.SetLogger(logr.Discard()) 57 | 58 | scheme := runtime.NewScheme() 59 | 60 | err = kvv1.AddToScheme(scheme) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | err = cdiv1.AddToScheme(scheme) 66 | if err != nil { 67 | return err 68 | } 69 | 70 | config, err := clientcmd.BuildConfigFromFlags("", cfg.kubeconfigFile) 71 | if err != nil { 72 | return fmt.Errorf("failed to read Kubernetes config: %w", err) 73 | } 74 | 75 | k8sClient, err := k8sclient.New(config, k8sclient.Options{ 76 | Scheme: scheme, 77 | }) 78 | if err != nil { 79 | return err 80 | } 81 | 82 | if cfg.omniAPIEndpoint == "" { 83 | return fmt.Errorf("omni-api-endpoint flag is not set") 84 | } 85 | 86 | volumeOpts := []v1.PersistentVolumeMode{ 87 | v1.PersistentVolumeBlock, 88 | v1.PersistentVolumeFilesystem, 89 | } 90 | 91 | if cfg.dataVolumeMode != "" && slices.Index(volumeOpts, v1.PersistentVolumeMode(cfg.dataVolumeMode)) == -1 { 92 | return fmt.Errorf("data-volume-mode flags should be one of %s", volumeOpts) 93 | } 94 | 95 | provisioner := provider.NewProvisioner(k8sClient, cfg.namespace, cfg.dataVolumeMode) 96 | 97 | ip, err := infra.NewProvider(meta.ProviderID, provisioner, infra.ProviderConfig{ 98 | Name: cfg.providerName, 99 | Description: cfg.providerDescription, 100 | Icon: base64.RawStdEncoding.EncodeToString(icon), 101 | Schema: string(data.Schema), 102 | }) 103 | if err != nil { 104 | return fmt.Errorf("failed to create infra provider: %w", err) 105 | } 106 | 107 | logger.Info("starting infra provider") 108 | 109 | clientOptions := []client.Option{ 110 | client.WithInsecureSkipTLSVerify(cfg.insecureSkipVerify), 111 | } 112 | 113 | if cfg.serviceAccountKey != "" { 114 | clientOptions = append(clientOptions, client.WithServiceAccount(cfg.serviceAccountKey)) 115 | } 116 | 117 | return ip.Run(cmd.Context(), logger, infra.WithOmniEndpoint(cfg.omniAPIEndpoint), infra.WithClientOptions( 118 | clientOptions..., 119 | ), infra.WithEncodeRequestIDsIntoTokens()) 120 | }, 121 | } 122 | 123 | var cfg struct { 124 | omniAPIEndpoint string 125 | serviceAccountKey string 126 | providerName string 127 | providerDescription string 128 | kubeconfigFile string 129 | namespace string 130 | dataVolumeMode string 131 | insecureSkipVerify bool 132 | } 133 | 134 | func main() { 135 | if err := app(); err != nil { 136 | os.Exit(1) 137 | } 138 | } 139 | 140 | func app() error { 141 | ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGHUP, syscall.SIGTERM) 142 | defer cancel() 143 | 144 | return rootCmd.ExecuteContext(ctx) 145 | } 146 | 147 | func init() { 148 | rootCmd.Flags().StringVar(&cfg.omniAPIEndpoint, "omni-api-endpoint", os.Getenv("OMNI_ENDPOINT"), 149 | "the endpoint of the Omni API, if not set, defaults to OMNI_ENDPOINT env var.") 150 | rootCmd.Flags().StringVar(&meta.ProviderID, "id", meta.ProviderID, "the id of the infra provider, it is used to match the resources with the infra provider label.") 151 | rootCmd.Flags().StringVar(&cfg.serviceAccountKey, "omni-service-account-key", os.Getenv("OMNI_SERVICE_ACCOUNT_KEY"), "Omni service account key, if not set, defaults to OMNI_SERVICE_ACCOUNT_KEY.") 152 | rootCmd.Flags().StringVar(&cfg.providerName, "provider-name", "KubeVirt", "provider name as it appears in Omni") 153 | rootCmd.Flags().StringVar(&cfg.providerDescription, "provider-description", "KubeVirt infrastructure provider", "Provider description as it appears in Omni") 154 | rootCmd.Flags().StringVar(&cfg.kubeconfigFile, "kubeconfig-file", "~/.kube/config", "Kubeconfig file to use to connect to the cluster where KubeVirt is running") 155 | rootCmd.Flags().StringVar(&cfg.namespace, "namespace", "default", "Kubernetes namespace to use for the resources created by the provider") 156 | rootCmd.Flags().StringVar(&cfg.dataVolumeMode, "data-volume-mode", "", "DataVolume PVC type to use (Block|Filesystem)") 157 | rootCmd.Flags().BoolVar(&cfg.insecureSkipVerify, "insecure-skip-verify", false, "ignores untrusted certs on Omni side") 158 | } 159 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/siderolabs/omni-infra-provider-kubevirt 2 | 3 | go 1.25.3 4 | 5 | require ( 6 | github.com/cosi-project/runtime v1.12.0 7 | github.com/go-logr/logr v1.4.3 8 | github.com/google/uuid v1.6.0 9 | github.com/planetscale/vtprotobuf v0.6.1-0.20241121165744-79df5c4772f2 10 | github.com/siderolabs/go-pointer v1.0.1 11 | github.com/siderolabs/omni/client v1.3.0-beta.1.0.20251106113647-e38f0ffe52b0 12 | github.com/spf13/cobra v1.10.1 13 | go.uber.org/zap v1.27.0 14 | google.golang.org/protobuf v1.36.10 15 | k8s.io/api v0.35.0-alpha.1 16 | k8s.io/apimachinery v0.35.0-alpha.1 17 | k8s.io/client-go v0.35.0-alpha.1 18 | kubevirt.io/api v1.5.2 19 | kubevirt.io/containerized-data-importer-api v1.62.0 20 | sigs.k8s.io/controller-runtime v0.21.0 21 | ) 22 | 23 | require ( 24 | cel.dev/expr v0.24.0 // indirect 25 | github.com/ProtonMail/go-crypto v1.3.0 // indirect 26 | github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect 27 | github.com/ProtonMail/gopenpgp/v2 v2.9.0 // indirect 28 | github.com/adrg/xdg v0.5.3 // indirect 29 | github.com/antlr4-go/antlr/v4 v4.13.1 // indirect 30 | github.com/blang/semver/v4 v4.0.0 // indirect 31 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 32 | github.com/cloudflare/circl v1.6.1 // indirect 33 | github.com/containerd/go-cni v1.1.13 // indirect 34 | github.com/containernetworking/cni v1.3.0 // indirect 35 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 36 | github.com/dustin/go-humanize v1.0.1 // indirect 37 | github.com/emicklei/go-restful/v3 v3.13.0 // indirect 38 | github.com/evanphx/json-patch/v5 v5.9.11 // indirect 39 | github.com/fxamacker/cbor/v2 v2.9.0 // indirect 40 | github.com/gertd/go-pluralize v0.2.1 // indirect 41 | github.com/go-openapi/jsonpointer v0.22.0 // indirect 42 | github.com/go-openapi/jsonreference v0.21.1 // indirect 43 | github.com/go-openapi/swag v0.24.1 // indirect 44 | github.com/go-openapi/swag/cmdutils v0.24.0 // indirect 45 | github.com/go-openapi/swag/conv v0.24.0 // indirect 46 | github.com/go-openapi/swag/fileutils v0.24.0 // indirect 47 | github.com/go-openapi/swag/jsonname v0.24.0 // indirect 48 | github.com/go-openapi/swag/jsonutils v0.24.0 // indirect 49 | github.com/go-openapi/swag/loading v0.24.0 // indirect 50 | github.com/go-openapi/swag/mangling v0.24.0 // indirect 51 | github.com/go-openapi/swag/netutils v0.24.0 // indirect 52 | github.com/go-openapi/swag/stringutils v0.24.0 // indirect 53 | github.com/go-openapi/swag/typeutils v0.24.0 // indirect 54 | github.com/go-openapi/swag/yamlutils v0.24.0 // indirect 55 | github.com/gogo/protobuf v1.3.2 // indirect 56 | github.com/google/cel-go v0.26.1 // indirect 57 | github.com/google/gnostic-models v0.7.0 // indirect 58 | github.com/google/go-cmp v0.7.0 // indirect 59 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect 60 | github.com/hashicorp/errwrap v1.1.0 // indirect 61 | github.com/hashicorp/go-multierror v1.1.1 // indirect 62 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 63 | github.com/josharian/intern v1.0.0 // indirect 64 | github.com/jsimonetti/rtnetlink/v2 v2.0.5 // indirect 65 | github.com/json-iterator/go v1.1.12 // indirect 66 | github.com/jxskiss/base62 v1.1.0 // indirect 67 | github.com/klauspost/compress v1.18.1 // indirect 68 | github.com/mailru/easyjson v0.9.0 // indirect 69 | github.com/mdlayher/ethtool v0.5.0 // indirect 70 | github.com/mdlayher/genetlink v1.3.2 // indirect 71 | github.com/mdlayher/netlink v1.8.0 // indirect 72 | github.com/mdlayher/socket v0.5.1 // indirect 73 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 74 | github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect 75 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 76 | github.com/opencontainers/runtime-spec v1.2.1 // indirect 77 | github.com/openshift/custom-resource-status v1.1.2 // indirect 78 | github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 // indirect 79 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect 80 | github.com/pkg/errors v0.9.1 // indirect 81 | github.com/ryanuber/go-glob v1.0.0 // indirect 82 | github.com/sasha-s/go-deadlock v0.3.6 // indirect 83 | github.com/siderolabs/crypto v0.6.4 // indirect 84 | github.com/siderolabs/gen v0.8.6 // indirect 85 | github.com/siderolabs/go-api-signature v0.3.9 // indirect 86 | github.com/siderolabs/image-factory v0.8.4 // indirect 87 | github.com/siderolabs/net v0.4.0 // indirect 88 | github.com/siderolabs/proto-codec v0.1.2 // indirect 89 | github.com/siderolabs/protoenc v0.2.4 // indirect 90 | github.com/siderolabs/siderolink v0.3.15 // indirect 91 | github.com/siderolabs/talos/pkg/machinery v1.12.0-alpha.2.0.20251104112157-92eeaa4826cf // indirect 92 | github.com/spf13/pflag v1.0.10 // indirect 93 | github.com/stoewer/go-strcase v1.3.1 // indirect 94 | github.com/x448/float16 v0.8.4 // indirect 95 | go.uber.org/multierr v1.11.0 // indirect 96 | go.yaml.in/yaml/v2 v2.4.3 // indirect 97 | go.yaml.in/yaml/v3 v3.0.4 // indirect 98 | go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect 99 | go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect 100 | golang.org/x/crypto v0.43.0 // indirect 101 | golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b // indirect 102 | golang.org/x/net v0.46.0 // indirect 103 | golang.org/x/oauth2 v0.32.0 // indirect 104 | golang.org/x/sync v0.17.0 // indirect 105 | golang.org/x/sys v0.37.0 // indirect 106 | golang.org/x/term v0.36.0 // indirect 107 | golang.org/x/text v0.30.0 // indirect 108 | golang.org/x/time v0.14.0 // indirect 109 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect 110 | golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb // indirect 111 | golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 // indirect 112 | google.golang.org/genproto/googleapis/api v0.0.0-20251020155222-88f65dc88635 // indirect 113 | google.golang.org/genproto/googleapis/rpc v0.0.0-20251020155222-88f65dc88635 // indirect 114 | google.golang.org/grpc v1.76.0 // indirect 115 | gopkg.in/inf.v0 v0.9.1 // indirect 116 | gopkg.in/yaml.v3 v3.0.1 // indirect 117 | k8s.io/apiextensions-apiserver v0.33.3 // indirect 118 | k8s.io/klog/v2 v2.130.1 // indirect 119 | k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect 120 | k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect 121 | kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4 // indirect 122 | sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect 123 | sigs.k8s.io/randfill v1.0.0 // indirect 124 | sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect 125 | sigs.k8s.io/yaml v1.6.0 // indirect 126 | ) 127 | -------------------------------------------------------------------------------- /hack/certs/key.private: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PRIVATE KEY BLOCK----- 2 | 3 | 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 104 | hp/KSDr6GKR6H5ggj1v1tBWE95A= 105 | =pdI2 106 | -----END PGP PRIVATE KEY BLOCK----- 107 | -------------------------------------------------------------------------------- /api/specs/specs.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.34.2 4 | // protoc v4.24.4 5 | // source: specs/specs.proto 6 | 7 | package specs 8 | 9 | import ( 10 | reflect "reflect" 11 | sync "sync" 12 | 13 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 14 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 15 | _ "google.golang.org/protobuf/types/known/durationpb" 16 | _ "google.golang.org/protobuf/types/known/timestamppb" 17 | ) 18 | 19 | const ( 20 | // Verify that this generated code is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 22 | // Verify that runtime/protoimpl is sufficiently up-to-date. 23 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 24 | ) 25 | 26 | // MachineSpec is stored in Omni in the infra provisioner state. 27 | type MachineSpec struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` 33 | Schematic string `protobuf:"bytes,2,opt,name=schematic,proto3" json:"schematic,omitempty"` 34 | TalosVersion string `protobuf:"bytes,3,opt,name=talos_version,json=talosVersion,proto3" json:"talos_version,omitempty"` 35 | VolumeId string `protobuf:"bytes,4,opt,name=volume_id,json=volumeId,proto3" json:"volume_id,omitempty"` 36 | } 37 | 38 | func (x *MachineSpec) Reset() { 39 | *x = MachineSpec{} 40 | if protoimpl.UnsafeEnabled { 41 | mi := &file_specs_specs_proto_msgTypes[0] 42 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 43 | ms.StoreMessageInfo(mi) 44 | } 45 | } 46 | 47 | func (x *MachineSpec) String() string { 48 | return protoimpl.X.MessageStringOf(x) 49 | } 50 | 51 | func (*MachineSpec) ProtoMessage() {} 52 | 53 | func (x *MachineSpec) ProtoReflect() protoreflect.Message { 54 | mi := &file_specs_specs_proto_msgTypes[0] 55 | if protoimpl.UnsafeEnabled && x != nil { 56 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 57 | if ms.LoadMessageInfo() == nil { 58 | ms.StoreMessageInfo(mi) 59 | } 60 | return ms 61 | } 62 | return mi.MessageOf(x) 63 | } 64 | 65 | // Deprecated: Use MachineSpec.ProtoReflect.Descriptor instead. 66 | func (*MachineSpec) Descriptor() ([]byte, []int) { 67 | return file_specs_specs_proto_rawDescGZIP(), []int{0} 68 | } 69 | 70 | func (x *MachineSpec) GetUuid() string { 71 | if x != nil { 72 | return x.Uuid 73 | } 74 | return "" 75 | } 76 | 77 | func (x *MachineSpec) GetSchematic() string { 78 | if x != nil { 79 | return x.Schematic 80 | } 81 | return "" 82 | } 83 | 84 | func (x *MachineSpec) GetTalosVersion() string { 85 | if x != nil { 86 | return x.TalosVersion 87 | } 88 | return "" 89 | } 90 | 91 | func (x *MachineSpec) GetVolumeId() string { 92 | if x != nil { 93 | return x.VolumeId 94 | } 95 | return "" 96 | } 97 | 98 | var File_specs_specs_proto protoreflect.FileDescriptor 99 | 100 | var file_specs_specs_proto_rawDesc = []byte{ 101 | 0x0a, 0x11, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x70, 0x72, 102 | 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x65, 0x6d, 0x75, 0x73, 0x70, 0x65, 0x63, 0x73, 0x1a, 0x1f, 0x67, 103 | 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 104 | 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 105 | 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 106 | 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x81, 107 | 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 108 | 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 109 | 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x18, 110 | 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 111 | 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 112 | 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x56, 0x65, 113 | 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 114 | 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 115 | 0x49, 0x64, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 116 | 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6f, 0x6d, 0x6e, 0x69, 117 | 0x2d, 0x69, 0x6e, 0x66, 0x72, 0x61, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2d, 118 | 0x6b, 0x75, 0x62, 0x65, 0x76, 0x69, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x70, 0x65, 119 | 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 120 | } 121 | 122 | var ( 123 | file_specs_specs_proto_rawDescOnce sync.Once 124 | file_specs_specs_proto_rawDescData = file_specs_specs_proto_rawDesc 125 | ) 126 | 127 | func file_specs_specs_proto_rawDescGZIP() []byte { 128 | file_specs_specs_proto_rawDescOnce.Do(func() { 129 | file_specs_specs_proto_rawDescData = protoimpl.X.CompressGZIP(file_specs_specs_proto_rawDescData) 130 | }) 131 | return file_specs_specs_proto_rawDescData 132 | } 133 | 134 | var file_specs_specs_proto_msgTypes = make([]protoimpl.MessageInfo, 1) 135 | var file_specs_specs_proto_goTypes = []any{ 136 | (*MachineSpec)(nil), // 0: emuspecs.MachineSpec 137 | } 138 | var file_specs_specs_proto_depIdxs = []int32{ 139 | 0, // [0:0] is the sub-list for method output_type 140 | 0, // [0:0] is the sub-list for method input_type 141 | 0, // [0:0] is the sub-list for extension type_name 142 | 0, // [0:0] is the sub-list for extension extendee 143 | 0, // [0:0] is the sub-list for field type_name 144 | } 145 | 146 | func init() { file_specs_specs_proto_init() } 147 | func file_specs_specs_proto_init() { 148 | if File_specs_specs_proto != nil { 149 | return 150 | } 151 | if !protoimpl.UnsafeEnabled { 152 | file_specs_specs_proto_msgTypes[0].Exporter = func(v any, i int) any { 153 | switch v := v.(*MachineSpec); i { 154 | case 0: 155 | return &v.state 156 | case 1: 157 | return &v.sizeCache 158 | case 2: 159 | return &v.unknownFields 160 | default: 161 | return nil 162 | } 163 | } 164 | } 165 | type x struct{} 166 | out := protoimpl.TypeBuilder{ 167 | File: protoimpl.DescBuilder{ 168 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 169 | RawDescriptor: file_specs_specs_proto_rawDesc, 170 | NumEnums: 0, 171 | NumMessages: 1, 172 | NumExtensions: 0, 173 | NumServices: 0, 174 | }, 175 | GoTypes: file_specs_specs_proto_goTypes, 176 | DependencyIndexes: file_specs_specs_proto_depIdxs, 177 | MessageInfos: file_specs_specs_proto_msgTypes, 178 | }.Build() 179 | File_specs_specs_proto = out.File 180 | file_specs_specs_proto_rawDesc = nil 181 | file_specs_specs_proto_goTypes = nil 182 | file_specs_specs_proto_depIdxs = nil 183 | } 184 | -------------------------------------------------------------------------------- /hack/test/integration.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eoux pipefail 4 | 5 | TMP="/tmp/kubevirt-e2e" 6 | mkdir -p "${TMP}" 7 | 8 | # Settings. 9 | 10 | TALOS_VERSION=1.11.5 11 | OMNI_VERSION=${OMNI_VERSION:-latest} 12 | K8S_VERSION="${K8S_VERSION:-1.33.5}" 13 | 14 | ARTIFACTS=_out 15 | JOIN_TOKEN=testonly 16 | RUN_DIR=$(pwd) 17 | PLATFORM=$(uname -s | tr "[:upper:]" "[:lower:]") 18 | 19 | export KUBECONFIG=${TMP}/kubeconfig 20 | 21 | # Download required artifacts. 22 | 23 | mkdir -p ${ARTIFACTS} 24 | 25 | [ -f ${ARTIFACTS}/talosctl ] || (crane export ghcr.io/siderolabs/talosctl:latest | tar x -C ${ARTIFACTS}) 26 | 27 | # Schematic without any customizations 28 | SCHEMATIC_ID="376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba" 29 | 30 | TALOSCTL="${ARTIFACTS}/talosctl" 31 | KUBECTL="${TMP}/kubectl" 32 | OMNICTL="${TMP}/omnictl" 33 | 34 | curl -Lo ${OMNICTL} $(curl https://api.github.com/repos/siderolabs/omni/releases/latest | jq -r '.assets[] | select(.name | contains ("omnictl-linux-amd64")) | .browser_download_url') 35 | chmod +x ${OMNICTL} 36 | 37 | curl -Lo ${KUBECTL} "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/${PLATFORM}/amd64/kubectl" 38 | chmod +x ${KUBECTL} 39 | 40 | # Build registry mirror args. 41 | 42 | if [[ "${CI:-false}" == "true" ]]; then 43 | REGISTRY_MIRROR_FLAGS=() 44 | 45 | for registry in docker.io k8s.gcr.io quay.io gcr.io ghcr.io registry.k8s.io factory.talos.dev; do 46 | service="registry-${registry//./-}.ci.svc" 47 | addr=$(python3 -c "import socket; print(socket.gethostbyname('${service}'))") 48 | 49 | REGISTRY_MIRROR_FLAGS+=("--registry-mirror=${registry}=http://${addr}:5000") 50 | done 51 | else 52 | # use the value from the environment, if present 53 | REGISTRY_MIRROR_FLAGS=("${REGISTRY_MIRROR_FLAGS:-}") 54 | fi 55 | 56 | CREATED_CLUSTER="kubevirt-test-$(echo $RANDOM | md5sum | head -c 10)" 57 | 58 | function cleanup() { 59 | # gather container logs 60 | if [[ ! -z ${KUBECONFIG} ]]; then 61 | ${KUBECTL} get vm -A || true 62 | ${KUBECTL} get vmi -A || true 63 | ${KUBECTL} get datavolume -A || true 64 | fi 65 | 66 | if [[ "${CI:-false}" == "false" ]]; then 67 | rm -rf ${TMP} 68 | 69 | if [[ ! -z ${CREATED_CLUSTER} ]]; then 70 | echo "destroying created cluster" 71 | ${TALOSCTL} cluster destroy --name=${CREATED_CLUSTER} --provisioner=qemu || true 72 | rm -rf ~/.talos/clusters/${CREATED_CLUSTER} 73 | fi 74 | 75 | docker rm -f omni-integration vault-dev 76 | fi 77 | 78 | rm -rf _out/omni/ 79 | } 80 | 81 | trap cleanup EXIT SIGINT 82 | 83 | # Start Vault. 84 | 85 | docker run --rm -d --cap-add=IPC_LOCK -p 8200:8200 -e 'VAULT_DEV_ROOT_TOKEN_ID=dev-o-token' --name vault-dev hashicorp/vault:1.15 86 | 87 | sleep 10 88 | 89 | # Load key into Vault. 90 | 91 | docker cp hack/certs/key.private vault-dev:/tmp/key.private 92 | docker exec -e VAULT_ADDR='http://0.0.0.0:8200' -e VAULT_TOKEN=dev-o-token vault-dev \ 93 | vault kv put -mount=secret omni-private-key \ 94 | private-key=@/tmp/key.private 95 | 96 | sleep 5 97 | 98 | # Launch Omni in the background. 99 | 100 | export BASE_URL=https://localhost:8099/ 101 | export AUTH_USERNAME="${AUTH0_TEST_USERNAME}" 102 | export AUTH0_CLIENT_ID="${AUTH0_CLIENT_ID}" 103 | export AUTH0_DOMAIN="${AUTH0_DOMAIN}" 104 | 105 | mkdir -p _out/omni/ 106 | 107 | docker run -it -d --network host -v ./hack/certs:/certs \ 108 | -v $(pwd)/_out/omni:/_out \ 109 | --cap-add=NET_ADMIN \ 110 | --device=/dev/net/tun \ 111 | -e SIDEROLINK_DEV_JOIN_TOKEN="${JOIN_TOKEN}" \ 112 | -e VAULT_TOKEN=dev-o-token \ 113 | -e VAULT_ADDR='http://127.0.0.1:8200' \ 114 | --name omni \ 115 | ghcr.io/siderolabs/omni:${OMNI_VERSION} \ 116 | --siderolink-wireguard-advertised-addr 10.11.0.1:50180 \ 117 | --siderolink-api-advertised-url "grpc://10.11.0.1:8090" \ 118 | --machine-api-bind-addr 0.0.0.0:8090 \ 119 | --siderolink-wireguard-bind-addr 0.0.0.0:50180 \ 120 | --event-sink-port 8091 \ 121 | --auth-auth0-enabled true \ 122 | --advertised-api-url "${BASE_URL}" \ 123 | --auth-auth0-client-id "${AUTH0_CLIENT_ID}" \ 124 | --auth-auth0-domain "${AUTH0_DOMAIN}" \ 125 | --initial-users "${AUTH_USERNAME}" \ 126 | --private-key-source "vault://secret/omni-private-key" \ 127 | --public-key-files "/certs/key.public" \ 128 | --bind-addr 0.0.0.0:8099 \ 129 | --key /certs/localhost-key.pem \ 130 | --cert /certs/localhost.pem \ 131 | --etcd-embedded-unsafe-fsync=true \ 132 | --create-initial-service-account \ 133 | --initial-service-account-key-path=/_out/key \ 134 | "${REGISTRY_MIRROR_FLAGS[@]}" 135 | 136 | docker logs -f omni &> ${TMP}/omni.log & 137 | 138 | echo "creating cluster ${CREATED_CLUSTER}" 139 | TAG="v${TALOS_VERSION}" ${TALOSCTL} cluster create \ 140 | --name=${CREATED_CLUSTER} \ 141 | --kubernetes-version=v${K8S_VERSION} \ 142 | ${REGISTRY_MIRROR_FLAGS} \ 143 | --provisioner=qemu \ 144 | --cidr 10.11.0.0/24 \ 145 | --vmlinuz-path="https://factory.talos.dev/image/${SCHEMATIC_ID}/v${TALOS_VERSION}/kernel-amd64" \ 146 | --initrd-path="https://factory.talos.dev/image/${SCHEMATIC_ID}/v${TALOS_VERSION}/initramfs-amd64.xz" \ 147 | --controlplanes=3 \ 148 | --workers=1 \ 149 | --cpus-workers 16.0 \ 150 | --memory 4096 \ 151 | --memory-workers=32768 \ 152 | --mtu 1430 \ 153 | --config-patch @hack/test/configpatch.yaml \ 154 | --disk=65536 155 | 156 | ${TALOSCTL} config nodes 10.11.0.2 157 | ${TALOSCTL} kubeconfig -f ${TMP}/kubeconfig 158 | 159 | # install kubevirt 160 | 161 | export RELEASE=$(curl https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt) 162 | 163 | ${KUBECTL} apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml 164 | 165 | ${KUBECTL} apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml 166 | 167 | ${KUBECTL} apply -f https://github.com/kubevirt/containerized-data-importer/releases/download/v1.62.0/cdi-operator.yaml 168 | ${KUBECTL} apply -f hack/test/manifests/cdi-cr.yaml 169 | ${KUBECTL} apply -f hack/test/manifests/local-path-storage.yaml 170 | 171 | ${KUBECTL} patch kubevirt -n kubevirt kubevirt --type='json' -p='[{"op": "replace", "path": "/spec/configuration", "value": {"developerConfiguration": {"featureGates": ["ExpandDisks"]}}}]' 172 | 173 | ${KUBECTL} -n kubevirt wait kv kubevirt --for condition=Available --timeout=10m 174 | 175 | # Launch infra provider in the background 176 | 177 | export OMNI_ENDPOINT=https://localhost:8099 178 | export OMNI_SERVICE_ACCOUNT_KEY=$(cat _out/omni/key) 179 | 180 | ${OMNICTL} --insecure-skip-tls-verify infraprovider create kubevirt | tail -n5 | head -n2 | awk '{print "export " $0}' > ${TMP}/env 181 | 182 | source ${TMP}/env 183 | 184 | nice -n 10 ${ARTIFACTS}/omni-infra-provider-kubevirt-linux-amd64 \ 185 | --kubeconfig-file=${KUBECONFIG} \ 186 | --omni-api-endpoint https://localhost:8099 \ 187 | --data-volume-mode Filesystem \ 188 | --insecure-skip-verify& 189 | 190 | docker run \ 191 | -v $(pwd)/hack/certs:/etc/ssl/certs \ 192 | -e SSL_CERT_DIR=/etc/ssl/certs \ 193 | -e OMNI_SERVICE_ACCOUNT_KEY=$(cat _out/omni/key) \ 194 | --network host \ 195 | ghcr.io/siderolabs/omni-integration-test:${OMNI_VERSION} \ 196 | --omni.endpoint https://localhost:8099 \ 197 | --omni.talos-version=${TALOS_VERSION} \ 198 | --test.run "TestIntegration/Suites/(ScaleUpAndDownAutoProvisionMachineSets)" \ 199 | --omni.infra-provider=kubevirt \ 200 | --omni.scale-timeout 5m \ 201 | --omni.provider-data='{disk_size: 8, cores: 4, memory: 2048, architecture: amd64}' \ 202 | --test.failfast \ 203 | --omni.kubernetes-version=${K8S_VERSION} \ 204 | --test.v 205 | -------------------------------------------------------------------------------- /api/specs/specs_vtproto.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. 2 | // protoc-gen-go-vtproto version: v0.6.0 3 | // source: specs/specs.proto 4 | 5 | package specs 6 | 7 | import ( 8 | fmt "fmt" 9 | io "io" 10 | 11 | protohelpers "github.com/planetscale/vtprotobuf/protohelpers" 12 | proto "google.golang.org/protobuf/proto" 13 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | func (m *MachineSpec) CloneVT() *MachineSpec { 24 | if m == nil { 25 | return (*MachineSpec)(nil) 26 | } 27 | r := new(MachineSpec) 28 | r.Uuid = m.Uuid 29 | r.Schematic = m.Schematic 30 | r.TalosVersion = m.TalosVersion 31 | r.VolumeId = m.VolumeId 32 | if len(m.unknownFields) > 0 { 33 | r.unknownFields = make([]byte, len(m.unknownFields)) 34 | copy(r.unknownFields, m.unknownFields) 35 | } 36 | return r 37 | } 38 | 39 | func (m *MachineSpec) CloneMessageVT() proto.Message { 40 | return m.CloneVT() 41 | } 42 | 43 | func (this *MachineSpec) EqualVT(that *MachineSpec) bool { 44 | if this == that { 45 | return true 46 | } else if this == nil || that == nil { 47 | return false 48 | } 49 | if this.Uuid != that.Uuid { 50 | return false 51 | } 52 | if this.Schematic != that.Schematic { 53 | return false 54 | } 55 | if this.TalosVersion != that.TalosVersion { 56 | return false 57 | } 58 | if this.VolumeId != that.VolumeId { 59 | return false 60 | } 61 | return string(this.unknownFields) == string(that.unknownFields) 62 | } 63 | 64 | func (this *MachineSpec) EqualMessageVT(thatMsg proto.Message) bool { 65 | that, ok := thatMsg.(*MachineSpec) 66 | if !ok { 67 | return false 68 | } 69 | return this.EqualVT(that) 70 | } 71 | func (m *MachineSpec) MarshalVT() (dAtA []byte, err error) { 72 | if m == nil { 73 | return nil, nil 74 | } 75 | size := m.SizeVT() 76 | dAtA = make([]byte, size) 77 | n, err := m.MarshalToSizedBufferVT(dAtA[:size]) 78 | if err != nil { 79 | return nil, err 80 | } 81 | return dAtA[:n], nil 82 | } 83 | 84 | func (m *MachineSpec) MarshalToVT(dAtA []byte) (int, error) { 85 | size := m.SizeVT() 86 | return m.MarshalToSizedBufferVT(dAtA[:size]) 87 | } 88 | 89 | func (m *MachineSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { 90 | if m == nil { 91 | return 0, nil 92 | } 93 | i := len(dAtA) 94 | _ = i 95 | var l int 96 | _ = l 97 | if m.unknownFields != nil { 98 | i -= len(m.unknownFields) 99 | copy(dAtA[i:], m.unknownFields) 100 | } 101 | if len(m.VolumeId) > 0 { 102 | i -= len(m.VolumeId) 103 | copy(dAtA[i:], m.VolumeId) 104 | i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.VolumeId))) 105 | i-- 106 | dAtA[i] = 0x22 107 | } 108 | if len(m.TalosVersion) > 0 { 109 | i -= len(m.TalosVersion) 110 | copy(dAtA[i:], m.TalosVersion) 111 | i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.TalosVersion))) 112 | i-- 113 | dAtA[i] = 0x1a 114 | } 115 | if len(m.Schematic) > 0 { 116 | i -= len(m.Schematic) 117 | copy(dAtA[i:], m.Schematic) 118 | i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Schematic))) 119 | i-- 120 | dAtA[i] = 0x12 121 | } 122 | if len(m.Uuid) > 0 { 123 | i -= len(m.Uuid) 124 | copy(dAtA[i:], m.Uuid) 125 | i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Uuid))) 126 | i-- 127 | dAtA[i] = 0xa 128 | } 129 | return len(dAtA) - i, nil 130 | } 131 | 132 | func (m *MachineSpec) SizeVT() (n int) { 133 | if m == nil { 134 | return 0 135 | } 136 | var l int 137 | _ = l 138 | l = len(m.Uuid) 139 | if l > 0 { 140 | n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) 141 | } 142 | l = len(m.Schematic) 143 | if l > 0 { 144 | n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) 145 | } 146 | l = len(m.TalosVersion) 147 | if l > 0 { 148 | n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) 149 | } 150 | l = len(m.VolumeId) 151 | if l > 0 { 152 | n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) 153 | } 154 | n += len(m.unknownFields) 155 | return n 156 | } 157 | 158 | func (m *MachineSpec) UnmarshalVT(dAtA []byte) error { 159 | l := len(dAtA) 160 | iNdEx := 0 161 | for iNdEx < l { 162 | preIndex := iNdEx 163 | var wire uint64 164 | for shift := uint(0); ; shift += 7 { 165 | if shift >= 64 { 166 | return protohelpers.ErrIntOverflow 167 | } 168 | if iNdEx >= l { 169 | return io.ErrUnexpectedEOF 170 | } 171 | b := dAtA[iNdEx] 172 | iNdEx++ 173 | wire |= uint64(b&0x7F) << shift 174 | if b < 0x80 { 175 | break 176 | } 177 | } 178 | fieldNum := int32(wire >> 3) 179 | wireType := int(wire & 0x7) 180 | if wireType == 4 { 181 | return fmt.Errorf("proto: MachineSpec: wiretype end group for non-group") 182 | } 183 | if fieldNum <= 0 { 184 | return fmt.Errorf("proto: MachineSpec: illegal tag %d (wire type %d)", fieldNum, wire) 185 | } 186 | switch fieldNum { 187 | case 1: 188 | if wireType != 2 { 189 | return fmt.Errorf("proto: wrong wireType = %d for field Uuid", wireType) 190 | } 191 | var stringLen uint64 192 | for shift := uint(0); ; shift += 7 { 193 | if shift >= 64 { 194 | return protohelpers.ErrIntOverflow 195 | } 196 | if iNdEx >= l { 197 | return io.ErrUnexpectedEOF 198 | } 199 | b := dAtA[iNdEx] 200 | iNdEx++ 201 | stringLen |= uint64(b&0x7F) << shift 202 | if b < 0x80 { 203 | break 204 | } 205 | } 206 | intStringLen := int(stringLen) 207 | if intStringLen < 0 { 208 | return protohelpers.ErrInvalidLength 209 | } 210 | postIndex := iNdEx + intStringLen 211 | if postIndex < 0 { 212 | return protohelpers.ErrInvalidLength 213 | } 214 | if postIndex > l { 215 | return io.ErrUnexpectedEOF 216 | } 217 | m.Uuid = string(dAtA[iNdEx:postIndex]) 218 | iNdEx = postIndex 219 | case 2: 220 | if wireType != 2 { 221 | return fmt.Errorf("proto: wrong wireType = %d for field Schematic", wireType) 222 | } 223 | var stringLen uint64 224 | for shift := uint(0); ; shift += 7 { 225 | if shift >= 64 { 226 | return protohelpers.ErrIntOverflow 227 | } 228 | if iNdEx >= l { 229 | return io.ErrUnexpectedEOF 230 | } 231 | b := dAtA[iNdEx] 232 | iNdEx++ 233 | stringLen |= uint64(b&0x7F) << shift 234 | if b < 0x80 { 235 | break 236 | } 237 | } 238 | intStringLen := int(stringLen) 239 | if intStringLen < 0 { 240 | return protohelpers.ErrInvalidLength 241 | } 242 | postIndex := iNdEx + intStringLen 243 | if postIndex < 0 { 244 | return protohelpers.ErrInvalidLength 245 | } 246 | if postIndex > l { 247 | return io.ErrUnexpectedEOF 248 | } 249 | m.Schematic = string(dAtA[iNdEx:postIndex]) 250 | iNdEx = postIndex 251 | case 3: 252 | if wireType != 2 { 253 | return fmt.Errorf("proto: wrong wireType = %d for field TalosVersion", wireType) 254 | } 255 | var stringLen uint64 256 | for shift := uint(0); ; shift += 7 { 257 | if shift >= 64 { 258 | return protohelpers.ErrIntOverflow 259 | } 260 | if iNdEx >= l { 261 | return io.ErrUnexpectedEOF 262 | } 263 | b := dAtA[iNdEx] 264 | iNdEx++ 265 | stringLen |= uint64(b&0x7F) << shift 266 | if b < 0x80 { 267 | break 268 | } 269 | } 270 | intStringLen := int(stringLen) 271 | if intStringLen < 0 { 272 | return protohelpers.ErrInvalidLength 273 | } 274 | postIndex := iNdEx + intStringLen 275 | if postIndex < 0 { 276 | return protohelpers.ErrInvalidLength 277 | } 278 | if postIndex > l { 279 | return io.ErrUnexpectedEOF 280 | } 281 | m.TalosVersion = string(dAtA[iNdEx:postIndex]) 282 | iNdEx = postIndex 283 | case 4: 284 | if wireType != 2 { 285 | return fmt.Errorf("proto: wrong wireType = %d for field VolumeId", wireType) 286 | } 287 | var stringLen uint64 288 | for shift := uint(0); ; shift += 7 { 289 | if shift >= 64 { 290 | return protohelpers.ErrIntOverflow 291 | } 292 | if iNdEx >= l { 293 | return io.ErrUnexpectedEOF 294 | } 295 | b := dAtA[iNdEx] 296 | iNdEx++ 297 | stringLen |= uint64(b&0x7F) << shift 298 | if b < 0x80 { 299 | break 300 | } 301 | } 302 | intStringLen := int(stringLen) 303 | if intStringLen < 0 { 304 | return protohelpers.ErrInvalidLength 305 | } 306 | postIndex := iNdEx + intStringLen 307 | if postIndex < 0 { 308 | return protohelpers.ErrInvalidLength 309 | } 310 | if postIndex > l { 311 | return io.ErrUnexpectedEOF 312 | } 313 | m.VolumeId = string(dAtA[iNdEx:postIndex]) 314 | iNdEx = postIndex 315 | default: 316 | iNdEx = preIndex 317 | skippy, err := protohelpers.Skip(dAtA[iNdEx:]) 318 | if err != nil { 319 | return err 320 | } 321 | if (skippy < 0) || (iNdEx+skippy) < 0 { 322 | return protohelpers.ErrInvalidLength 323 | } 324 | if (iNdEx + skippy) > l { 325 | return io.ErrUnexpectedEOF 326 | } 327 | m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) 328 | iNdEx += skippy 329 | } 330 | } 331 | 332 | if iNdEx > l { 333 | return io.ErrUnexpectedEOF 334 | } 335 | return nil 336 | } 337 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile-upstream:1.19.0-labs 2 | 3 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 4 | # 5 | # Generated on 2025-11-06T14:58:30Z by kres 4ba9b0c. 6 | 7 | ARG TOOLCHAIN=scratch 8 | 9 | FROM ghcr.io/siderolabs/ca-certificates:v1.11.0 AS image-ca-certificates 10 | 11 | FROM ghcr.io/siderolabs/fhs:v1.11.0 AS image-fhs 12 | 13 | # runs markdownlint 14 | FROM docker.io/oven/bun:1.3.0-alpine AS lint-markdown 15 | WORKDIR /src 16 | RUN bun i markdownlint-cli@0.45.0 sentences-per-line@0.3.0 17 | COPY .markdownlint.json . 18 | COPY ./README.md ./README.md 19 | RUN bunx markdownlint --ignore "CHANGELOG.md" --ignore "**/node_modules/**" --ignore '**/hack/chglog/**' --rules sentences-per-line . 20 | 21 | # collects proto specs 22 | FROM scratch AS proto-specs 23 | ADD api/specs/specs.proto /api/specs/ 24 | 25 | # base toolchain image 26 | FROM --platform=${BUILDPLATFORM} ${TOOLCHAIN} AS toolchain 27 | RUN apk --update --no-cache add bash build-base curl jq protoc protobuf-dev 28 | 29 | # build tools 30 | FROM --platform=${BUILDPLATFORM} toolchain AS tools 31 | ENV GO111MODULE=on 32 | ARG CGO_ENABLED 33 | ENV CGO_ENABLED=${CGO_ENABLED} 34 | ARG GOTOOLCHAIN 35 | ENV GOTOOLCHAIN=${GOTOOLCHAIN} 36 | ARG GOEXPERIMENT 37 | ENV GOEXPERIMENT=${GOEXPERIMENT} 38 | ENV GOPATH=/go 39 | ARG GOIMPORTS_VERSION 40 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install golang.org/x/tools/cmd/goimports@v${GOIMPORTS_VERSION} 41 | RUN mv /go/bin/goimports /bin 42 | ARG GOMOCK_VERSION 43 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install go.uber.org/mock/mockgen@v${GOMOCK_VERSION} 44 | RUN mv /go/bin/mockgen /bin 45 | ARG PROTOBUF_GO_VERSION 46 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install google.golang.org/protobuf/cmd/protoc-gen-go@v${PROTOBUF_GO_VERSION} 47 | RUN mv /go/bin/protoc-gen-go /bin 48 | ARG GRPC_GO_VERSION 49 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${GRPC_GO_VERSION} 50 | RUN mv /go/bin/protoc-gen-go-grpc /bin 51 | ARG GRPC_GATEWAY_VERSION 52 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v${GRPC_GATEWAY_VERSION} 53 | RUN mv /go/bin/protoc-gen-grpc-gateway /bin 54 | ARG VTPROTOBUF_VERSION 55 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v${VTPROTOBUF_VERSION} 56 | RUN mv /go/bin/protoc-gen-go-vtproto /bin 57 | ARG DEEPCOPY_VERSION 58 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install github.com/siderolabs/deep-copy@${DEEPCOPY_VERSION} \ 59 | && mv /go/bin/deep-copy /bin/deep-copy 60 | ARG GOLANGCILINT_VERSION 61 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${GOLANGCILINT_VERSION} \ 62 | && mv /go/bin/golangci-lint /bin/golangci-lint 63 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go install golang.org/x/vuln/cmd/govulncheck@latest \ 64 | && mv /go/bin/govulncheck /bin/govulncheck 65 | ARG GOFUMPT_VERSION 66 | RUN go install mvdan.cc/gofumpt@${GOFUMPT_VERSION} \ 67 | && mv /go/bin/gofumpt /bin/gofumpt 68 | 69 | # tools and sources 70 | FROM tools AS base 71 | WORKDIR /src 72 | COPY go.mod go.mod 73 | COPY go.sum go.sum 74 | RUN cd . 75 | RUN --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go mod download 76 | RUN --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go mod verify 77 | COPY ./api ./api 78 | COPY ./cmd ./cmd 79 | COPY ./internal ./internal 80 | RUN --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go list -mod=readonly all >/dev/null 81 | 82 | # runs protobuf compiler 83 | FROM tools AS proto-compile 84 | COPY --from=proto-specs / / 85 | RUN protoc -I/api --go_out=paths=source_relative:/api --go-grpc_out=paths=source_relative:/api --go-vtproto_out=paths=source_relative:/api --go-vtproto_opt=features=marshal+unmarshal+size+equal+clone /api/specs/specs.proto 86 | RUN rm /api/specs/specs.proto 87 | RUN goimports -w -local github.com/siderolabs/omni-infra-provider-kubevirt /api 88 | RUN gofumpt -w /api 89 | 90 | # runs gofumpt 91 | FROM base AS lint-gofumpt 92 | RUN FILES="$(gofumpt -l .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumpt -w .':\n${FILES}"; exit 1) 93 | 94 | # runs golangci-lint 95 | FROM base AS lint-golangci-lint 96 | WORKDIR /src 97 | COPY .golangci.yml . 98 | ENV GOGC=50 99 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/root/.cache/golangci-lint,id=omni-infra-provider-kubevirt/root/.cache/golangci-lint,sharing=locked --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg golangci-lint run --config .golangci.yml 100 | 101 | # runs golangci-lint fmt 102 | FROM base AS lint-golangci-lint-fmt-run 103 | WORKDIR /src 104 | COPY .golangci.yml . 105 | ENV GOGC=50 106 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/root/.cache/golangci-lint,id=omni-infra-provider-kubevirt/root/.cache/golangci-lint,sharing=locked --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg golangci-lint fmt --config .golangci.yml 107 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/root/.cache/golangci-lint,id=omni-infra-provider-kubevirt/root/.cache/golangci-lint,sharing=locked --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg golangci-lint run --fix --issues-exit-code 0 --config .golangci.yml 108 | 109 | # runs govulncheck 110 | FROM base AS lint-govulncheck 111 | WORKDIR /src 112 | COPY --chmod=0755 hack/govulncheck.sh ./hack/govulncheck.sh 113 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg ./hack/govulncheck.sh ./... 114 | 115 | # runs unit-tests with race detector 116 | FROM base AS unit-tests-race 117 | WORKDIR /src 118 | ARG TESTPKGS 119 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg --mount=type=cache,target=/tmp,id=omni-infra-provider-kubevirt/tmp CGO_ENABLED=1 go test -race ${TESTPKGS} 120 | 121 | # runs unit-tests 122 | FROM base AS unit-tests-run 123 | WORKDIR /src 124 | ARG TESTPKGS 125 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg --mount=type=cache,target=/tmp,id=omni-infra-provider-kubevirt/tmp go test -covermode=atomic -coverprofile=coverage.txt -coverpkg=${TESTPKGS} ${TESTPKGS} 126 | 127 | # cleaned up specs and compiled versions 128 | FROM scratch AS generate 129 | COPY --from=proto-compile /api/ /api/ 130 | 131 | # clean golangci-lint fmt output 132 | FROM scratch AS lint-golangci-lint-fmt 133 | COPY --from=lint-golangci-lint-fmt-run /src . 134 | 135 | FROM scratch AS unit-tests 136 | COPY --from=unit-tests-run /src/coverage.txt /coverage-unit-tests.txt 137 | 138 | # builds omni-infra-provider-kubevirt-linux-amd64 139 | FROM base AS omni-infra-provider-kubevirt-linux-amd64-build 140 | COPY --from=generate / / 141 | WORKDIR /src/cmd/omni-infra-provider-kubevirt 142 | ARG GO_BUILDFLAGS 143 | ARG GO_LDFLAGS 144 | RUN --mount=type=cache,target=/root/.cache/go-build,id=omni-infra-provider-kubevirt/root/.cache/go-build --mount=type=cache,target=/go/pkg,id=omni-infra-provider-kubevirt/go/pkg go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /omni-infra-provider-kubevirt-linux-amd64 145 | 146 | FROM scratch AS omni-infra-provider-kubevirt-linux-amd64 147 | COPY --from=omni-infra-provider-kubevirt-linux-amd64-build /omni-infra-provider-kubevirt-linux-amd64 /omni-infra-provider-kubevirt-linux-amd64 148 | 149 | FROM omni-infra-provider-kubevirt-linux-${TARGETARCH} AS omni-infra-provider-kubevirt 150 | 151 | FROM scratch AS omni-infra-provider-kubevirt-all 152 | COPY --from=omni-infra-provider-kubevirt-linux-amd64 / / 153 | 154 | FROM scratch AS image-omni-infra-provider-kubevirt 155 | ARG TARGETARCH 156 | COPY --from=omni-infra-provider-kubevirt omni-infra-provider-kubevirt-linux-${TARGETARCH} /omni-infra-provider-kubevirt 157 | COPY --from=image-fhs / / 158 | COPY --from=image-ca-certificates / / 159 | LABEL org.opencontainers.image.source=https://github.com/siderolabs/omni-infra-provider-kubevirt 160 | ENTRYPOINT ["/omni-infra-provider-kubevirt"] 161 | 162 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-11-06T15:39:32Z by kres 4ba9b0c. 4 | 5 | concurrency: 6 | group: ${{ github.head_ref || github.run_id }} 7 | cancel-in-progress: true 8 | "on": 9 | push: 10 | branches: 11 | - main 12 | - release-* 13 | tags: 14 | - v* 15 | pull_request: 16 | branches: 17 | - main 18 | - release-* 19 | name: default 20 | jobs: 21 | default: 22 | permissions: 23 | actions: read 24 | contents: write 25 | issues: read 26 | packages: write 27 | pull-requests: read 28 | runs-on: 29 | group: large 30 | if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/')) 31 | steps: 32 | - name: gather-system-info 33 | id: system-info 34 | uses: kenchan0130/actions-system-info@v1.4.0 35 | continue-on-error: true 36 | - name: print-system-info 37 | run: | 38 | MEMORY_GB=$((${{ steps.system-info.outputs.totalmem }}/1024/1024/1024)) 39 | 40 | OUTPUTS=( 41 | "CPU Core: ${{ steps.system-info.outputs.cpu-core }}" 42 | "CPU Model: ${{ steps.system-info.outputs.cpu-model }}" 43 | "Hostname: ${{ steps.system-info.outputs.hostname }}" 44 | "NodeName: ${NODE_NAME}" 45 | "Kernel release: ${{ steps.system-info.outputs.kernel-release }}" 46 | "Kernel version: ${{ steps.system-info.outputs.kernel-version }}" 47 | "Name: ${{ steps.system-info.outputs.name }}" 48 | "Platform: ${{ steps.system-info.outputs.platform }}" 49 | "Release: ${{ steps.system-info.outputs.release }}" 50 | "Total memory: ${MEMORY_GB} GB" 51 | ) 52 | 53 | for OUTPUT in "${OUTPUTS[@]}";do 54 | echo "${OUTPUT}" 55 | done 56 | continue-on-error: true 57 | - name: checkout 58 | uses: actions/checkout@v5 59 | - name: Unshallow 60 | run: | 61 | git fetch --prune --unshallow 62 | - name: Set up Docker Buildx 63 | id: setup-buildx 64 | uses: docker/setup-buildx-action@v3 65 | with: 66 | driver: remote 67 | endpoint: tcp://buildkit-amd64.ci.svc.cluster.local:1234 68 | timeout-minutes: 10 69 | - name: Mask secrets 70 | run: | 71 | echo "$(sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | "::add-mask::" + .value')" 72 | - name: Set secrets for job 73 | run: | 74 | sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | .key + "=" + .value' >> "$GITHUB_ENV" 75 | - name: base 76 | run: | 77 | make base 78 | - name: omni-infra-provider-kubevirt 79 | run: | 80 | make omni-infra-provider-kubevirt 81 | - name: Login to registry 82 | if: github.event_name != 'pull_request' 83 | uses: docker/login-action@v3 84 | with: 85 | password: ${{ secrets.GITHUB_TOKEN }} 86 | registry: ghcr.io 87 | username: ${{ github.repository_owner }} 88 | - name: image-omni-infra-provider-kubevirt 89 | run: | 90 | make image-omni-infra-provider-kubevirt 91 | - name: push-omni-infra-provider-kubevirt 92 | if: github.event_name != 'pull_request' 93 | env: 94 | PUSH: "true" 95 | run: | 96 | make image-omni-infra-provider-kubevirt 97 | - name: push-omni-infra-provider-kubevirt-latest 98 | if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' 99 | env: 100 | PUSH: "true" 101 | run: | 102 | make image-omni-infra-provider-kubevirt IMAGE_TAG=latest 103 | - name: run-integration-test 104 | run: | 105 | sudo -E make run-integration-test 106 | - name: Generate executable list 107 | run: | 108 | find _out -type f -executable > _out/executable-artifacts 109 | - name: save-artifacts 110 | uses: actions/upload-artifact@v4 111 | with: 112 | name: artifacts 113 | path: |- 114 | _out 115 | !_out/omni/ 116 | retention-days: "5" 117 | - name: save-talos-logs-artifacts 118 | if: always() 119 | uses: actions/upload-artifact@v4 120 | with: 121 | name: talos-logs 122 | path: |- 123 | ~/.talos/clusters/**/*.log 124 | !~/.talos/clusters/**/swtpm.log 125 | retention-days: "5" 126 | - name: save-omni-logs-artifacts 127 | if: always() 128 | uses: actions/upload-artifact@v4 129 | with: 130 | name: omni-logs 131 | path: /tmp/kubevirt-e2e/*.log 132 | retention-days: "5" 133 | - name: Generate Checksums 134 | if: startsWith(github.ref, 'refs/tags/') 135 | run: | 136 | cd _out 137 | sha256sum omni-infra-provider-kubevirt-* > sha256sum.txt 138 | sha512sum omni-infra-provider-kubevirt-* > sha512sum.txt 139 | - name: release-notes 140 | if: startsWith(github.ref, 'refs/tags/') 141 | run: | 142 | make release-notes 143 | - name: Release 144 | if: startsWith(github.ref, 'refs/tags/') 145 | uses: softprops/action-gh-release@v2 146 | with: 147 | body_path: _out/RELEASE_NOTES.md 148 | draft: "true" 149 | files: |- 150 | _out/omni-infra-provider-kubevirt-* 151 | _out/sha*.txt 152 | lint: 153 | runs-on: 154 | group: generic 155 | if: github.event_name == 'pull_request' 156 | needs: 157 | - default 158 | steps: 159 | - name: gather-system-info 160 | id: system-info 161 | uses: kenchan0130/actions-system-info@v1.4.0 162 | continue-on-error: true 163 | - name: print-system-info 164 | run: | 165 | MEMORY_GB=$((${{ steps.system-info.outputs.totalmem }}/1024/1024/1024)) 166 | 167 | OUTPUTS=( 168 | "CPU Core: ${{ steps.system-info.outputs.cpu-core }}" 169 | "CPU Model: ${{ steps.system-info.outputs.cpu-model }}" 170 | "Hostname: ${{ steps.system-info.outputs.hostname }}" 171 | "NodeName: ${NODE_NAME}" 172 | "Kernel release: ${{ steps.system-info.outputs.kernel-release }}" 173 | "Kernel version: ${{ steps.system-info.outputs.kernel-version }}" 174 | "Name: ${{ steps.system-info.outputs.name }}" 175 | "Platform: ${{ steps.system-info.outputs.platform }}" 176 | "Release: ${{ steps.system-info.outputs.release }}" 177 | "Total memory: ${MEMORY_GB} GB" 178 | ) 179 | 180 | for OUTPUT in "${OUTPUTS[@]}";do 181 | echo "${OUTPUT}" 182 | done 183 | continue-on-error: true 184 | - name: checkout 185 | uses: actions/checkout@v5 186 | - name: Unshallow 187 | run: | 188 | git fetch --prune --unshallow 189 | - name: Set up Docker Buildx 190 | id: setup-buildx 191 | uses: docker/setup-buildx-action@v3 192 | with: 193 | driver: remote 194 | endpoint: tcp://buildkit-amd64.ci.svc.cluster.local:1234 195 | timeout-minutes: 10 196 | - name: Mask secrets 197 | run: | 198 | echo "$(sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | "::add-mask::" + .value')" 199 | - name: Set secrets for job 200 | run: | 201 | sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | .key + "=" + .value' >> "$GITHUB_ENV" 202 | - name: lint 203 | run: | 204 | make lint 205 | unit-tests: 206 | runs-on: 207 | group: generic 208 | if: github.event_name == 'pull_request' 209 | needs: 210 | - default 211 | steps: 212 | - name: gather-system-info 213 | id: system-info 214 | uses: kenchan0130/actions-system-info@v1.4.0 215 | continue-on-error: true 216 | - name: print-system-info 217 | run: | 218 | MEMORY_GB=$((${{ steps.system-info.outputs.totalmem }}/1024/1024/1024)) 219 | 220 | OUTPUTS=( 221 | "CPU Core: ${{ steps.system-info.outputs.cpu-core }}" 222 | "CPU Model: ${{ steps.system-info.outputs.cpu-model }}" 223 | "Hostname: ${{ steps.system-info.outputs.hostname }}" 224 | "NodeName: ${NODE_NAME}" 225 | "Kernel release: ${{ steps.system-info.outputs.kernel-release }}" 226 | "Kernel version: ${{ steps.system-info.outputs.kernel-version }}" 227 | "Name: ${{ steps.system-info.outputs.name }}" 228 | "Platform: ${{ steps.system-info.outputs.platform }}" 229 | "Release: ${{ steps.system-info.outputs.release }}" 230 | "Total memory: ${MEMORY_GB} GB" 231 | ) 232 | 233 | for OUTPUT in "${OUTPUTS[@]}";do 234 | echo "${OUTPUT}" 235 | done 236 | continue-on-error: true 237 | - name: checkout 238 | uses: actions/checkout@v5 239 | - name: Unshallow 240 | run: | 241 | git fetch --prune --unshallow 242 | - name: Set up Docker Buildx 243 | id: setup-buildx 244 | uses: docker/setup-buildx-action@v3 245 | with: 246 | driver: remote 247 | endpoint: tcp://buildkit-amd64.ci.svc.cluster.local:1234 248 | timeout-minutes: 10 249 | - name: Mask secrets 250 | run: | 251 | echo "$(sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | "::add-mask::" + .value')" 252 | - name: Set secrets for job 253 | run: | 254 | sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | .key + "=" + .value' >> "$GITHUB_ENV" 255 | - name: unit-tests 256 | run: | 257 | make unit-tests 258 | - name: unit-tests-race 259 | run: | 260 | make unit-tests-race 261 | -------------------------------------------------------------------------------- /internal/pkg/provider/provision.go: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | // Package provider implements KubeVirt infra provider core. 6 | package provider 7 | 8 | import ( 9 | "context" 10 | "crypto/sha256" 11 | "encoding/hex" 12 | "fmt" 13 | "net/url" 14 | "time" 15 | 16 | "github.com/google/uuid" 17 | pointer "github.com/siderolabs/go-pointer" 18 | "github.com/siderolabs/omni/client/pkg/constants" 19 | "github.com/siderolabs/omni/client/pkg/infra/provision" 20 | "github.com/siderolabs/omni/client/pkg/omni/resources/infra" 21 | "go.uber.org/zap" 22 | v1 "k8s.io/api/core/v1" 23 | "k8s.io/apimachinery/pkg/api/errors" 24 | "k8s.io/apimachinery/pkg/api/resource" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | "k8s.io/apimachinery/pkg/types" 27 | kvv1 "kubevirt.io/api/core/v1" 28 | cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" 29 | "sigs.k8s.io/controller-runtime/pkg/client" 30 | 31 | "github.com/siderolabs/omni-infra-provider-kubevirt/internal/pkg/provider/data" 32 | "github.com/siderolabs/omni-infra-provider-kubevirt/internal/pkg/provider/resources" 33 | ) 34 | 35 | // Provisioner implements Talos emulator infra provider. 36 | type Provisioner struct { 37 | k8sClient client.Client 38 | namespace string 39 | volumeMode v1.PersistentVolumeMode 40 | } 41 | 42 | // NewProvisioner creates a new provisioner. 43 | func NewProvisioner(k8sClient client.Client, namespace, volumeMode string) *Provisioner { 44 | return &Provisioner{ 45 | k8sClient: k8sClient, 46 | namespace: namespace, 47 | volumeMode: v1.PersistentVolumeMode(volumeMode), 48 | } 49 | } 50 | 51 | // ProvisionSteps implements infra.Provisioner. 52 | // 53 | //nolint:gocognit,gocyclo,cyclop,maintidx 54 | func (p *Provisioner) ProvisionSteps() []provision.Step[*resources.Machine] { 55 | return []provision.Step[*resources.Machine]{ 56 | provision.NewStep("validateRequest", func(_ context.Context, _ *zap.Logger, pctx provision.Context[*resources.Machine]) error { 57 | if len(pctx.GetRequestID()) > 62 { 58 | return fmt.Errorf("the machine request name can not be longer than 63 characters") 59 | } 60 | 61 | return nil 62 | }), 63 | provision.NewStep("createSchematic", func(ctx context.Context, logger *zap.Logger, pctx provision.Context[*resources.Machine]) error { 64 | schematic, err := pctx.GenerateSchematicID(ctx, logger, 65 | provision.WithExtraKernelArgs("console=ttyS0,38400n8"), 66 | provision.WithoutConnectionParams(), 67 | ) 68 | if err != nil { 69 | return err 70 | } 71 | 72 | pctx.State.TypedSpec().Value.Schematic = schematic 73 | 74 | return nil 75 | }), 76 | provision.NewStep("ensureVolume", func(ctx context.Context, _ *zap.Logger, pctx provision.Context[*resources.Machine]) error { 77 | pctx.State.TypedSpec().Value.TalosVersion = pctx.GetTalosVersion() 78 | 79 | url, err := url.Parse(constants.ImageFactoryBaseURL) 80 | if err != nil { 81 | return err 82 | } 83 | 84 | var data data.Data 85 | 86 | err = pctx.UnmarshalProviderData(&data) 87 | if err != nil { 88 | return err 89 | } 90 | 91 | url = url.JoinPath("image", 92 | pctx.State.TypedSpec().Value.Schematic, 93 | pctx.GetTalosVersion(), 94 | fmt.Sprintf("nocloud-%s.qcow2", data.Architecture), 95 | ) 96 | 97 | hash := sha256.New() 98 | 99 | if _, err = hash.Write([]byte(url.String())); err != nil { 100 | return err 101 | } 102 | 103 | volumeID := hex.EncodeToString(hash.Sum(nil)) 104 | 105 | pctx.State.TypedSpec().Value.VolumeId = volumeID 106 | 107 | volume := cdiv1.DataVolume{ 108 | Spec: cdiv1.DataVolumeSpec{ 109 | Source: &cdiv1.DataVolumeSource{ 110 | HTTP: &cdiv1.DataVolumeSourceHTTP{ 111 | URL: url.String(), 112 | }, 113 | }, 114 | PVC: &v1.PersistentVolumeClaimSpec{ 115 | AccessModes: []v1.PersistentVolumeAccessMode{ 116 | v1.ReadWriteOnce, 117 | }, 118 | Resources: v1.VolumeResourceRequirements{ 119 | Requests: v1.ResourceList{ 120 | v1.ResourceStorage: resource.MustParse("5Gi"), 121 | }, 122 | }, 123 | }, 124 | }, 125 | } 126 | 127 | if p.volumeMode != "" { 128 | volume.Spec.PVC.VolumeMode = &p.volumeMode 129 | } 130 | 131 | if volume.Annotations == nil { 132 | volume.Annotations = map[string]string{} 133 | } 134 | 135 | volume.Annotations["cdi.kubevirt.io/storage.bind.immediate.requested"] = "true" 136 | 137 | vol := &cdiv1.DataVolume{} 138 | 139 | err = p.k8sClient.Get(ctx, client.ObjectKey{ 140 | Namespace: p.namespace, 141 | Name: volumeID, 142 | }, vol) 143 | if err != nil && !errors.IsNotFound(err) { 144 | return err 145 | } 146 | 147 | if vol.Status.Phase == cdiv1.Succeeded { 148 | return nil 149 | } 150 | 151 | if vol.Name == "" { 152 | volume.Name = volumeID 153 | volume.Namespace = p.namespace 154 | 155 | if err = p.k8sClient.Create(ctx, &volume); err != nil { 156 | return err 157 | } 158 | } 159 | 160 | return provision.NewRetryInterval(time.Second * 10) 161 | }), 162 | provision.NewStep("syncMachine", func(ctx context.Context, logger *zap.Logger, pctx provision.Context[*resources.Machine]) error { 163 | if pctx.State.TypedSpec().Value.Uuid == "" { 164 | pctx.State.TypedSpec().Value.Uuid = uuid.NewString() 165 | } 166 | 167 | logger = logger.With(zap.String("id", pctx.State.TypedSpec().Value.Uuid)) 168 | 169 | vm := &kvv1.VirtualMachine{} 170 | 171 | err := p.k8sClient.Get(ctx, client.ObjectKey{ 172 | Namespace: p.namespace, 173 | Name: pctx.GetRequestID(), 174 | }, vm) 175 | if err != nil && !errors.IsNotFound(err) { 176 | return err 177 | } 178 | 179 | if vm.Name != "" && vm.Status.Ready { 180 | logger.Info("machine is ready") 181 | 182 | return nil 183 | } 184 | 185 | var data data.Data 186 | 187 | err = pctx.UnmarshalProviderData(&data) 188 | if err != nil { 189 | return err 190 | } 191 | 192 | vm.Spec.Running = pointer.To(true) 193 | 194 | if vm.Spec.Template == nil { 195 | vm.Spec.Template = &kvv1.VirtualMachineInstanceTemplateSpec{ 196 | Spec: kvv1.VirtualMachineInstanceSpec{ 197 | Domain: kvv1.DomainSpec{ 198 | Resources: kvv1.ResourceRequirements{ 199 | Requests: v1.ResourceList{}, 200 | }, 201 | }, 202 | }, 203 | } 204 | } 205 | 206 | vm.Spec.Template.Spec.Domain.Firmware = &kvv1.Firmware{ 207 | UUID: types.UID(pctx.State.TypedSpec().Value.Uuid), 208 | } 209 | 210 | vm.Spec.Template.Spec.Architecture = data.Architecture 211 | vm.Spec.Template.Spec.Domain.CPU = &kvv1.CPU{ 212 | Cores: uint32(data.Cores), 213 | } 214 | 215 | vm.Spec.Template.Spec.Domain.Resources.Requests[v1.ResourceMemory] = *resource.NewQuantity(int64(data.Memory)*1024*1024, resource.DecimalSI) 216 | 217 | vm.Spec.Template.Spec.Networks = []kvv1.Network{ 218 | *kvv1.DefaultPodNetwork(), 219 | } 220 | 221 | networkInterface := *kvv1.DefaultBridgeNetworkInterface() 222 | if data.NetworkBinding == "passt" { 223 | networkInterface = kvv1.Interface{ 224 | Name: networkInterface.Name, 225 | Binding: &kvv1.PluginBinding{ 226 | Name: "passt", 227 | }, 228 | } 229 | } 230 | 231 | vm.Spec.Template.Spec.Domain.Devices = kvv1.Devices{ 232 | Disks: []kvv1.Disk{ 233 | { 234 | Name: "kv", 235 | BootOrder: pointer.To(uint(1)), 236 | DiskDevice: kvv1.DiskDevice{ 237 | Disk: &kvv1.DiskTarget{ 238 | Bus: kvv1.DiskBusVirtio, 239 | }, 240 | }, 241 | }, 242 | }, 243 | Interfaces: []kvv1.Interface{ 244 | networkInterface, 245 | }, 246 | } 247 | 248 | vm.Spec.Template.Spec.Volumes = []kvv1.Volume{ 249 | { 250 | Name: "kv", 251 | VolumeSource: kvv1.VolumeSource{ 252 | DataVolume: &kvv1.DataVolumeSource{ 253 | Name: pctx.GetRequestID(), 254 | }, 255 | }, 256 | }, 257 | { 258 | Name: "cloudinitdisk", 259 | VolumeSource: kvv1.VolumeSource{ 260 | CloudInitNoCloud: &kvv1.CloudInitNoCloudSource{ 261 | UserData: pctx.ConnectionParams.JoinConfig, 262 | NetworkData: `version: 1`, 263 | }, 264 | }, 265 | }, 266 | } 267 | 268 | volumeTemplate := kvv1.DataVolumeTemplateSpec{ 269 | ObjectMeta: metav1.ObjectMeta{ 270 | Name: pctx.GetRequestID(), 271 | }, 272 | Spec: cdiv1.DataVolumeSpec{ 273 | PVC: &v1.PersistentVolumeClaimSpec{ 274 | AccessModes: []v1.PersistentVolumeAccessMode{ 275 | v1.ReadWriteOnce, 276 | }, 277 | Resources: v1.VolumeResourceRequirements{ 278 | Requests: v1.ResourceList{ 279 | v1.ResourceStorage: resource.MustParse(fmt.Sprintf("%dGi", data.DiskSize)), 280 | }, 281 | }, 282 | }, 283 | Source: &cdiv1.DataVolumeSource{ 284 | PVC: &cdiv1.DataVolumeSourcePVC{ 285 | Name: pctx.State.TypedSpec().Value.VolumeId, 286 | Namespace: p.namespace, 287 | }, 288 | }, 289 | }, 290 | } 291 | 292 | if p.volumeMode != "" { 293 | volumeTemplate.Spec.PVC.VolumeMode = &p.volumeMode 294 | } 295 | 296 | vm.Spec.DataVolumeTemplates = []kvv1.DataVolumeTemplateSpec{ 297 | volumeTemplate, 298 | } 299 | 300 | if vm.Name == "" { 301 | vm.Name = pctx.GetRequestID() 302 | vm.Namespace = p.namespace 303 | 304 | if err = p.k8sClient.Create(ctx, vm); err != nil { 305 | return err 306 | } 307 | } else { 308 | if err = p.k8sClient.Update(ctx, vm); err != nil && !errors.IsConflict(err) { 309 | return err 310 | } 311 | } 312 | 313 | return provision.NewRetryInterval(time.Second * 10) 314 | }), 315 | } 316 | } 317 | 318 | // Deprovision implements infra.Provisioner. 319 | func (p *Provisioner) Deprovision(ctx context.Context, logger *zap.Logger, _ *resources.Machine, machineRequest *infra.MachineRequest) error { 320 | var vm kvv1.VirtualMachine 321 | 322 | err := p.k8sClient.Get(ctx, client.ObjectKey{ 323 | Namespace: p.namespace, 324 | Name: machineRequest.Metadata().ID(), 325 | }, &vm) 326 | if err != nil && !errors.IsNotFound(err) { 327 | return err 328 | } 329 | 330 | if vm.Name == "" { 331 | logger.Info("machine deprovisioned") 332 | 333 | return nil 334 | } 335 | 336 | err = p.k8sClient.Delete(ctx, &kvv1.VirtualMachine{ 337 | ObjectMeta: metav1.ObjectMeta{ 338 | Name: machineRequest.Metadata().ID(), 339 | Namespace: p.namespace, 340 | }, 341 | }) 342 | if err != nil && !errors.IsNotFound(err) { 343 | return err 344 | } 345 | 346 | return provision.NewRetryInterval(time.Second * 5) 347 | } 348 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. 2 | # 3 | # Generated on 2025-11-06T14:58:30Z by kres 4ba9b0c. 4 | 5 | # common variables 6 | 7 | SHA := $(shell git describe --match=none --always --abbrev=8 --dirty) 8 | TAG := $(shell git describe --tag --always --dirty --match v[0-9]\*) 9 | ABBREV_TAG := $(shell git describe --tags >/dev/null 2>/dev/null && git describe --tag --always --match v[0-9]\* --abbrev=0 || echo 'undefined') 10 | BRANCH := $(shell git rev-parse --abbrev-ref HEAD) 11 | ARTIFACTS := _out 12 | IMAGE_TAG ?= $(TAG) 13 | OPERATING_SYSTEM := $(shell uname -s | tr '[:upper:]' '[:lower:]') 14 | GOARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/') 15 | WITH_DEBUG ?= false 16 | WITH_RACE ?= false 17 | REGISTRY ?= ghcr.io 18 | USERNAME ?= siderolabs 19 | REGISTRY_AND_USERNAME ?= $(REGISTRY)/$(USERNAME) 20 | PROTOBUF_GO_VERSION ?= 1.36.10 21 | GRPC_GO_VERSION ?= 1.5.1 22 | GRPC_GATEWAY_VERSION ?= 2.27.3 23 | VTPROTOBUF_VERSION ?= 0.6.0 24 | GOIMPORTS_VERSION ?= 0.38.0 25 | GOMOCK_VERSION ?= 0.6.0 26 | DEEPCOPY_VERSION ?= v0.5.8 27 | GOLANGCILINT_VERSION ?= v2.5.0 28 | GOFUMPT_VERSION ?= v0.9.1 29 | GO_VERSION ?= 1.25.3 30 | GO_BUILDFLAGS ?= 31 | GO_LDFLAGS ?= 32 | CGO_ENABLED ?= 0 33 | GOTOOLCHAIN ?= local 34 | GOEXPERIMENT ?= 35 | TESTPKGS ?= ./... 36 | KRES_IMAGE ?= ghcr.io/siderolabs/kres:latest 37 | CONFORMANCE_IMAGE ?= ghcr.io/siderolabs/conform:latest 38 | 39 | # docker build settings 40 | 41 | BUILD := docker buildx build 42 | PLATFORM ?= linux/amd64 43 | PROGRESS ?= auto 44 | PUSH ?= false 45 | CI_ARGS ?= 46 | BUILDKIT_MULTI_PLATFORM ?= 47 | COMMON_ARGS = --file=Dockerfile 48 | COMMON_ARGS += --provenance=false 49 | COMMON_ARGS += --progress=$(PROGRESS) 50 | COMMON_ARGS += --platform=$(PLATFORM) 51 | COMMON_ARGS += --build-arg=BUILDKIT_MULTI_PLATFORM=$(BUILDKIT_MULTI_PLATFORM) 52 | COMMON_ARGS += --push=$(PUSH) 53 | COMMON_ARGS += --build-arg=ARTIFACTS="$(ARTIFACTS)" 54 | COMMON_ARGS += --build-arg=SHA="$(SHA)" 55 | COMMON_ARGS += --build-arg=TAG="$(TAG)" 56 | COMMON_ARGS += --build-arg=ABBREV_TAG="$(ABBREV_TAG)" 57 | COMMON_ARGS += --build-arg=USERNAME="$(USERNAME)" 58 | COMMON_ARGS += --build-arg=REGISTRY="$(REGISTRY)" 59 | COMMON_ARGS += --build-arg=TOOLCHAIN="$(TOOLCHAIN)" 60 | COMMON_ARGS += --build-arg=CGO_ENABLED="$(CGO_ENABLED)" 61 | COMMON_ARGS += --build-arg=GO_BUILDFLAGS="$(GO_BUILDFLAGS)" 62 | COMMON_ARGS += --build-arg=GO_LDFLAGS="$(GO_LDFLAGS)" 63 | COMMON_ARGS += --build-arg=GOTOOLCHAIN="$(GOTOOLCHAIN)" 64 | COMMON_ARGS += --build-arg=GOEXPERIMENT="$(GOEXPERIMENT)" 65 | COMMON_ARGS += --build-arg=PROTOBUF_GO_VERSION="$(PROTOBUF_GO_VERSION)" 66 | COMMON_ARGS += --build-arg=GRPC_GO_VERSION="$(GRPC_GO_VERSION)" 67 | COMMON_ARGS += --build-arg=GRPC_GATEWAY_VERSION="$(GRPC_GATEWAY_VERSION)" 68 | COMMON_ARGS += --build-arg=VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)" 69 | COMMON_ARGS += --build-arg=GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)" 70 | COMMON_ARGS += --build-arg=GOMOCK_VERSION="$(GOMOCK_VERSION)" 71 | COMMON_ARGS += --build-arg=DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)" 72 | COMMON_ARGS += --build-arg=GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)" 73 | COMMON_ARGS += --build-arg=GOFUMPT_VERSION="$(GOFUMPT_VERSION)" 74 | COMMON_ARGS += --build-arg=TESTPKGS="$(TESTPKGS)" 75 | TOOLCHAIN ?= docker.io/golang:1.25-alpine 76 | 77 | # extra variables 78 | 79 | REMOVE_VOLUMES ?= false 80 | 81 | # help menu 82 | 83 | export define HELP_MENU_HEADER 84 | # Getting Started 85 | 86 | To build this project, you must have the following installed: 87 | 88 | - git 89 | - make 90 | - docker (19.03 or higher) 91 | 92 | ## Creating a Builder Instance 93 | 94 | The build process makes use of experimental Docker features (buildx). 95 | To enable experimental features, add 'experimental: "true"' to '/etc/docker/daemon.json' on 96 | Linux or enable experimental features in Docker GUI for Windows or Mac. 97 | 98 | To create a builder instance, run: 99 | 100 | docker buildx create --name local --use 101 | 102 | If running builds that needs to be cached aggresively create a builder instance with the following: 103 | 104 | docker buildx create --name local --use --config=config.toml 105 | 106 | config.toml contents: 107 | 108 | [worker.oci] 109 | gc = true 110 | gckeepstorage = 50000 111 | 112 | [[worker.oci.gcpolicy]] 113 | keepBytes = 10737418240 114 | keepDuration = 604800 115 | filters = [ "type==source.local", "type==exec.cachemount", "type==source.git.checkout"] 116 | [[worker.oci.gcpolicy]] 117 | all = true 118 | keepBytes = 53687091200 119 | 120 | If you already have a compatible builder instance, you may use that instead. 121 | 122 | ## Artifacts 123 | 124 | All artifacts will be output to ./$(ARTIFACTS). Images will be tagged with the 125 | registry "$(REGISTRY)", username "$(USERNAME)", and a dynamic tag (e.g. $(IMAGE):$(IMAGE_TAG)). 126 | The registry and username can be overridden by exporting REGISTRY, and USERNAME 127 | respectively. 128 | 129 | endef 130 | 131 | ifneq (, $(filter $(WITH_RACE), t true TRUE y yes 1)) 132 | GO_BUILDFLAGS += -race 133 | CGO_ENABLED := 1 134 | GO_LDFLAGS += -linkmode=external -extldflags '-static' 135 | endif 136 | 137 | ifneq (, $(filter $(WITH_DEBUG), t true TRUE y yes 1)) 138 | GO_BUILDFLAGS += -tags sidero.debug 139 | else 140 | GO_LDFLAGS += -s 141 | endif 142 | 143 | all: unit-tests omni-infra-provider-kubevirt image-omni-infra-provider-kubevirt lint 144 | 145 | $(ARTIFACTS): ## Creates artifacts directory. 146 | @mkdir -p $(ARTIFACTS) 147 | 148 | .PHONY: clean 149 | clean: ## Cleans up all artifacts. 150 | @rm -rf $(ARTIFACTS) 151 | 152 | target-%: ## Builds the specified target defined in the Dockerfile. The build result will only remain in the build cache. 153 | @$(BUILD) --target=$* $(COMMON_ARGS) $(TARGET_ARGS) $(CI_ARGS) . 154 | 155 | registry-%: ## Builds the specified target defined in the Dockerfile and the output is an image. The image is pushed to the registry if PUSH=true. 156 | @$(MAKE) target-$* TARGET_ARGS="--tag=$(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(IMAGE_TAG)" BUILDKIT_MULTI_PLATFORM=1 157 | 158 | local-%: ## Builds the specified target defined in the Dockerfile using the local output type. The build result will be output to the specified local destination. 159 | @$(MAKE) target-$* TARGET_ARGS="--output=type=local,dest=$(DEST) $(TARGET_ARGS)" 160 | @PLATFORM=$(PLATFORM) DEST=$(DEST) bash -c '\ 161 | for platform in $$(tr "," "\n" <<< "$$PLATFORM"); do \ 162 | directory="$${platform//\//_}"; \ 163 | if [[ -d "$$DEST/$$directory" ]]; then \ 164 | echo $$platform; \ 165 | mv -f "$$DEST/$$directory/"* $$DEST; \ 166 | rmdir "$$DEST/$$directory/"; \ 167 | fi; \ 168 | done' 169 | 170 | generate: ## Generate .proto definitions. 171 | @$(MAKE) local-$@ DEST=./ 172 | 173 | lint-golangci-lint: ## Runs golangci-lint linter. 174 | @$(MAKE) target-$@ 175 | 176 | lint-golangci-lint-fmt: ## Runs golangci-lint formatter and tries to fix issues automatically. 177 | @$(MAKE) local-$@ DEST=. 178 | 179 | lint-gofumpt: ## Runs gofumpt linter. 180 | @$(MAKE) target-$@ 181 | 182 | .PHONY: fmt 183 | fmt: ## Formats the source code 184 | @docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) \ 185 | bash -c "export GOTOOLCHAIN=local; \ 186 | export GO111MODULE=on; export GOPROXY=https://proxy.golang.org; \ 187 | go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) && \ 188 | gofumpt -w ." 189 | 190 | lint-govulncheck: ## Runs govulncheck linter. 191 | @$(MAKE) target-$@ 192 | 193 | .PHONY: base 194 | base: ## Prepare base toolchain 195 | @$(MAKE) target-$@ 196 | 197 | .PHONY: unit-tests 198 | unit-tests: ## Performs unit tests 199 | @$(MAKE) local-$@ DEST=$(ARTIFACTS) 200 | 201 | .PHONY: unit-tests-race 202 | unit-tests-race: ## Performs unit tests with race detection enabled. 203 | @$(MAKE) target-$@ 204 | 205 | .PHONY: $(ARTIFACTS)/omni-infra-provider-kubevirt-linux-amd64 206 | $(ARTIFACTS)/omni-infra-provider-kubevirt-linux-amd64: 207 | @$(MAKE) local-omni-infra-provider-kubevirt-linux-amd64 DEST=$(ARTIFACTS) 208 | 209 | .PHONY: omni-infra-provider-kubevirt-linux-amd64 210 | omni-infra-provider-kubevirt-linux-amd64: $(ARTIFACTS)/omni-infra-provider-kubevirt-linux-amd64 ## Builds executable for omni-infra-provider-kubevirt-linux-amd64. 211 | 212 | .PHONY: omni-infra-provider-kubevirt 213 | omni-infra-provider-kubevirt: omni-infra-provider-kubevirt-linux-amd64 ## Builds executables for omni-infra-provider-kubevirt. 214 | 215 | .PHONY: lint-markdown 216 | lint-markdown: ## Runs markdownlint. 217 | @$(MAKE) target-$@ 218 | 219 | .PHONY: lint 220 | lint: lint-golangci-lint lint-gofumpt lint-govulncheck lint-markdown ## Run all linters for the project. 221 | 222 | .PHONY: lint-fmt 223 | lint-fmt: lint-golangci-lint-fmt ## Run all linter formatters and fix up the source tree. 224 | 225 | .PHONY: image-omni-infra-provider-kubevirt 226 | image-omni-infra-provider-kubevirt: ## Builds image for omni-infra-provider-kubevirt. 227 | @$(MAKE) registry-$@ IMAGE_NAME="omni-infra-provider-kubevirt" 228 | 229 | .PHONY: docker-compose-up 230 | docker-compose-up: 231 | ARTIFACTS="$(ARTIFACTS)" SHA="$(SHA)" TAG="$(TAG)" USERNAME="$(USERNAME)" REGISTRY="$(REGISTRY)" PROTOBUF_TS_VERSION="$(PROTOBUF_TS_VERSION)" NODE_BUILD_ARGS="$(NODE_BUILD_ARGS)" TOOLCHAIN="$(TOOLCHAIN)" CGO_ENABLED="$(CGO_ENABLED)" GO_BUILDFLAGS="$(GO_BUILDFLAGS)" GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)" GOFUMPT_VERSION="$(GOFUMPT_VERSION)" GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)" PROTOBUF_GO_VERSION="$(PROTOBUF_GO_VERSION)" GRPC_GO_VERSION="$(GRPC_GO_VERSION)" GRPC_GATEWAY_VERSION="$(GRPC_GATEWAY_VERSION)" VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)" DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)" TESTPKGS="$(TESTPKGS)" COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 GO_LDFLAGS="$(GO_LDFLAGS)" docker compose -p talemu --file ./hack/compose/docker-compose.yml --file ./hack/compose/docker-compose.override.yml up --build 232 | 233 | .PHONY: docker-compose-down 234 | docker-compose-down: 235 | ARTIFACTS="$(ARTIFACTS)" SHA="$(SHA)" TAG="$(TAG)" USERNAME="$(USERNAME)" REGISTRY="$(REGISTRY)" PROTOBUF_TS_VERSION="$(PROTOBUF_TS_VERSION)" NODE_BUILD_ARGS="$(NODE_BUILD_ARGS)" TOOLCHAIN="$(TOOLCHAIN)" CGO_ENABLED="$(CGO_ENABLED)" GO_BUILDFLAGS="$(GO_BUILDFLAGS)" GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)" GOFUMPT_VERSION="$(GOFUMPT_VERSION)" GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)" PROTOBUF_GO_VERSION="$(PROTOBUF_GO_VERSION)" GRPC_GO_VERSION="$(GRPC_GO_VERSION)" GRPC_GATEWAY_VERSION="$(GRPC_GATEWAY_VERSION)" VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)" DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)" TESTPKGS="$(TESTPKGS)" COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 GO_LDFLAGS="$(GO_LDFLAGS)" docker compose -p talemu --file ./hack/compose/docker-compose.yml --file ./hack/compose/docker-compose.override.yml down --rmi local --remove-orphans --volumes=$(REMOVE_VOLUMES) 236 | 237 | run-integration-test: omni-infra-provider-kubevirt 238 | @hack/test/integration.sh 239 | 240 | .PHONY: rekres 241 | rekres: 242 | @docker pull $(KRES_IMAGE) 243 | @docker run --rm --net=host --user $(shell id -u):$(shell id -g) -v $(PWD):/src -w /src -e GITHUB_TOKEN $(KRES_IMAGE) 244 | 245 | .PHONY: help 246 | help: ## This help menu. 247 | @echo "$$HELP_MENU_HEADER" 248 | @grep -E '^[a-zA-Z%_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 249 | 250 | .PHONY: release-notes 251 | release-notes: $(ARTIFACTS) 252 | @ARTIFACTS=$(ARTIFACTS) ./hack/release.sh $@ $(ARTIFACTS)/RELEASE_NOTES.md $(TAG) 253 | 254 | .PHONY: conformance 255 | conformance: 256 | @docker pull $(CONFORMANCE_IMAGE) 257 | @docker run --rm -it -v $(PWD):/src -w /src $(CONFORMANCE_IMAGE) enforce 258 | 259 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= 2 | cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= 3 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 5 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 6 | github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= 7 | github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= 8 | github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= 9 | github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= 10 | github.com/ProtonMail/gopenpgp/v2 v2.9.0 h1:ruLzBmwe4dR1hdnrsEJ/S7psSBmV15gFttFUPP/+/kE= 11 | github.com/ProtonMail/gopenpgp/v2 v2.9.0/go.mod h1:IldDyh9Hv1ZCCYatTuuEt1XZJ0OPjxLpTarDfglih7s= 12 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 13 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 14 | github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= 15 | github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= 16 | github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= 17 | github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= 18 | github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= 19 | github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= 20 | github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= 21 | github.com/brianvoe/gofakeit/v7 v7.7.3 h1:RWOATEGpJ5EVg2nN8nlaEyaV/aB4d6c3GqYrbqQekss= 22 | github.com/brianvoe/gofakeit/v7 v7.7.3/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= 23 | github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 24 | github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 25 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 26 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 27 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 28 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 29 | github.com/cilium/ebpf v0.19.0 h1:Ro/rE64RmFBeA9FGjcTc+KmCeY6jXmryu6FfnzPRIao= 30 | github.com/cilium/ebpf v0.19.0/go.mod h1:fLCgMo3l8tZmAdM3B2XqdFzXBpwkcSTroaVqN08OWVY= 31 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 32 | github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= 33 | github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= 34 | github.com/containerd/go-cni v1.1.13 h1:eFSGOKlhoYNxpJ51KRIMHZNlg5UgocXEIEBGkY7Hnis= 35 | github.com/containerd/go-cni v1.1.13/go.mod h1:nTieub0XDRmvCZ9VI/SBG6PyqT95N4FIhxsauF1vSBI= 36 | github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo= 37 | github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4= 38 | github.com/cosi-project/runtime v1.12.0 h1:fsX1VKn9atthccDMhWDHM+t1hdW6eDKAPa2t/Rd/dfI= 39 | github.com/cosi-project/runtime v1.12.0/go.mod h1:/9fspODJfZrO5dQatMRgN440K8DjWP1jFSgiLX+FmQc= 40 | github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 41 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 42 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 43 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 44 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 45 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 46 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 47 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 48 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 49 | github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 50 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 51 | github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 52 | github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 53 | github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= 54 | github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 55 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 56 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 57 | github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 58 | github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= 59 | github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 60 | github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= 61 | github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= 62 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 63 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 64 | github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= 65 | github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= 66 | github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA= 67 | github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk= 68 | github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= 69 | github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= 70 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 71 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 72 | github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= 73 | github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 74 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 75 | github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= 76 | github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 77 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 78 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 79 | github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= 80 | github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= 81 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 82 | github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 83 | github.com/go-openapi/jsonpointer v0.22.0 h1:TmMhghgNef9YXxTu1tOopo+0BGEytxA+okbry0HjZsM= 84 | github.com/go-openapi/jsonpointer v0.22.0/go.mod h1:xt3jV88UtExdIkkL7NloURjRQjbeUgcxFblMjq2iaiU= 85 | github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= 86 | github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= 87 | github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= 88 | github.com/go-openapi/jsonreference v0.21.1 h1:bSKrcl8819zKiOgxkbVNRUBIr6Wwj9KYrDbMjRs0cDA= 89 | github.com/go-openapi/jsonreference v0.21.1/go.mod h1:PWs8rO4xxTUqKGu+lEvvCxD5k2X7QYkKAepJyCmSTT8= 90 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 91 | github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= 92 | github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= 93 | github.com/go-openapi/swag v0.24.1 h1:DPdYTZKo6AQCRqzwr/kGkxJzHhpKxZ9i/oX0zag+MF8= 94 | github.com/go-openapi/swag v0.24.1/go.mod h1:sm8I3lCPlspsBBwUm1t5oZeWZS0s7m/A+Psg0ooRU0A= 95 | github.com/go-openapi/swag/cmdutils v0.24.0 h1:KlRCffHwXFI6E5MV9n8o8zBRElpY4uK4yWyAMWETo9I= 96 | github.com/go-openapi/swag/cmdutils v0.24.0/go.mod h1:uxib2FAeQMByyHomTlsP8h1TtPd54Msu2ZDU/H5Vuf8= 97 | github.com/go-openapi/swag/conv v0.24.0 h1:ejB9+7yogkWly6pnruRX45D1/6J+ZxRu92YFivx54ik= 98 | github.com/go-openapi/swag/conv v0.24.0/go.mod h1:jbn140mZd7EW2g8a8Y5bwm8/Wy1slLySQQ0ND6DPc2c= 99 | github.com/go-openapi/swag/fileutils v0.24.0 h1:U9pCpqp4RUytnD689Ek/N1d2N/a//XCeqoH508H5oak= 100 | github.com/go-openapi/swag/fileutils v0.24.0/go.mod h1:3SCrCSBHyP1/N+3oErQ1gP+OX1GV2QYFSnrTbzwli90= 101 | github.com/go-openapi/swag/jsonname v0.24.0 h1:2wKS9bgRV/xB8c62Qg16w4AUiIrqqiniJFtZGi3dg5k= 102 | github.com/go-openapi/swag/jsonname v0.24.0/go.mod h1:GXqrPzGJe611P7LG4QB9JKPtUZ7flE4DOVechNaDd7Q= 103 | github.com/go-openapi/swag/jsonutils v0.24.0 h1:F1vE1q4pg1xtO3HTyJYRmEuJ4jmIp2iZ30bzW5XgZts= 104 | github.com/go-openapi/swag/jsonutils v0.24.0/go.mod h1:vBowZtF5Z4DDApIoxcIVfR8v0l9oq5PpYRUuteVu6f0= 105 | github.com/go-openapi/swag/loading v0.24.0 h1:ln/fWTwJp2Zkj5DdaX4JPiddFC5CHQpvaBKycOlceYc= 106 | github.com/go-openapi/swag/loading v0.24.0/go.mod h1:gShCN4woKZYIxPxbfbyHgjXAhO61m88tmjy0lp/LkJk= 107 | github.com/go-openapi/swag/mangling v0.24.0 h1:PGOQpViCOUroIeak/Uj/sjGAq9LADS3mOyjznmHy2pk= 108 | github.com/go-openapi/swag/mangling v0.24.0/go.mod h1:Jm5Go9LHkycsz0wfoaBDkdc4CkpuSnIEf62brzyCbhc= 109 | github.com/go-openapi/swag/netutils v0.24.0 h1:Bz02HRjYv8046Ycg/w80q3g9QCWeIqTvlyOjQPDjD8w= 110 | github.com/go-openapi/swag/netutils v0.24.0/go.mod h1:WRgiHcYTnx+IqfMCtu0hy9oOaPR0HnPbmArSRN1SkZM= 111 | github.com/go-openapi/swag/stringutils v0.24.0 h1:i4Z/Jawf9EvXOLUbT97O0HbPUja18VdBxeadyAqS1FM= 112 | github.com/go-openapi/swag/stringutils v0.24.0/go.mod h1:5nUXB4xA0kw2df5PRipZDslPJgJut+NjL7D25zPZ/4w= 113 | github.com/go-openapi/swag/typeutils v0.24.0 h1:d3szEGzGDf4L2y1gYOSSLeK6h46F+zibnEas2Jm/wIw= 114 | github.com/go-openapi/swag/typeutils v0.24.0/go.mod h1:q8C3Kmk/vh2VhpCLaoR2MVWOGP8y7Jc8l82qCTd1DYI= 115 | github.com/go-openapi/swag/yamlutils v0.24.0 h1:bhw4894A7Iw6ne+639hsBNRHg9iZg/ISrOVr+sJGp4c= 116 | github.com/go-openapi/swag/yamlutils v0.24.0/go.mod h1:DpKv5aYuaGm/sULePoeiG8uwMpZSfReo1HR3Ik0yaG8= 117 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= 118 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 119 | github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= 120 | github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 121 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 122 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 123 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 124 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 125 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 126 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 127 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 128 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 129 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 130 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 131 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 132 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 133 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 134 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 135 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 136 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 137 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 138 | github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= 139 | github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 140 | github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ= 141 | github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= 142 | github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= 143 | github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= 144 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 145 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 146 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 147 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 148 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 149 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 150 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 151 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 152 | github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 153 | github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 154 | github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= 155 | github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= 156 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 157 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 158 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 159 | github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= 160 | github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= 161 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 162 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 163 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= 164 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= 165 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 166 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 167 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 168 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 169 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 170 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 171 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 172 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 173 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 174 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 175 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 176 | github.com/jsimonetti/rtnetlink/v2 v2.0.5 h1:l5S9iedrSW4thUfgiU+Hzsnk1cOR0upGD5ttt6mirHw= 177 | github.com/jsimonetti/rtnetlink/v2 v2.0.5/go.mod h1:9yTlq3Ojr1rbmh/Y5L30/KIojpFhTRph2xKeZ+y+Pic= 178 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 179 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 180 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 181 | github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw= 182 | github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc= 183 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 184 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 185 | github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= 186 | github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= 187 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 188 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 189 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 190 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 191 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 192 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 193 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 194 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 195 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 196 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 197 | github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 198 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 199 | github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= 200 | github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= 201 | github.com/mdlayher/ethtool v0.5.0 h1:7MpuhvUE574uVQDfkXotePLdfSNetlx3GDikFcdlVQA= 202 | github.com/mdlayher/ethtool v0.5.0/go.mod h1:ROV9hwnETqDdpLv8E8WkCa8FymlkhFEeiB9cg3qzNkk= 203 | github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw= 204 | github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o= 205 | github.com/mdlayher/netlink v1.8.0 h1:e7XNIYJKD7hUct3Px04RuIGJbBxy1/c4nX7D5YyvvlM= 206 | github.com/mdlayher/netlink v1.8.0/go.mod h1:UhgKXUlDQhzb09DrCl2GuRNEglHmhYoWAHid9HK3594= 207 | github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= 208 | github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= 209 | github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws= 210 | github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= 211 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 212 | github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= 213 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 214 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 215 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 216 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 217 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 218 | github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= 219 | github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 220 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 221 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 222 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 223 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 224 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 225 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 226 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 227 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 228 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 229 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 230 | github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= 231 | github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= 232 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 233 | github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= 234 | github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= 235 | github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= 236 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 237 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 238 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 239 | github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 240 | github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= 241 | github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= 242 | github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= 243 | github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww= 244 | github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= 245 | github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= 246 | github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= 247 | github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= 248 | github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 h1:QTvNkZ5ylY0PGgA+Lih+GdboMLY/G9SEGLMEGVjTVA4= 249 | github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= 250 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= 251 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= 252 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 253 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 254 | github.com/planetscale/vtprotobuf v0.6.1-0.20241121165744-79df5c4772f2 h1:1sLMdKq4gNANTj0dUibycTLzpIEKVnLnbaEkxws78nw= 255 | github.com/planetscale/vtprotobuf v0.6.1-0.20241121165744-79df5c4772f2/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= 256 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 257 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 258 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 259 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 260 | github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= 261 | github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 262 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 263 | github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= 264 | github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 265 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= 266 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= 267 | github.com/sasha-s/go-deadlock v0.3.6 h1:TR7sfOnZ7x00tWPfD397Peodt57KzMDo+9Ae9rMiUmw= 268 | github.com/sasha-s/go-deadlock v0.3.6/go.mod h1:CUqNyyvMxTyjFqDT7MRg9mb4Dv/btmGTqSR+rky/UXo= 269 | github.com/siderolabs/crypto v0.6.4 h1:uMoe/X/mABOv6yOgvKcjmjIMdv6U8JegBXlPKtyjn3g= 270 | github.com/siderolabs/crypto v0.6.4/go.mod h1:39B7Mdrd8qTfEYOjsWPQOk7gLTWrEI30isAW+YYj9nk= 271 | github.com/siderolabs/gen v0.8.6 h1:pE6shuqov3L+5rEcAUJ/kY6iJofimljQw5G95P8a5c4= 272 | github.com/siderolabs/gen v0.8.6/go.mod h1:J9IbusbES2W6QWjtSHpDV9iPGZHc978h1+KJ4oQRspQ= 273 | github.com/siderolabs/go-api-signature v0.3.9 h1:JfXTR0J9LOsvQXT0kIdnSm+F3qe+ustLnBuC65H0qvc= 274 | github.com/siderolabs/go-api-signature v0.3.9/go.mod h1:VcilCqp2k2bYjFhzsxdc2JPqGIcOkHjeG2bLLm1NGeA= 275 | github.com/siderolabs/go-pointer v1.0.1 h1:f7Yi4IK1jptS8yrT9GEbwhmGcVxvPQgBUG/weH3V3DM= 276 | github.com/siderolabs/go-pointer v1.0.1/go.mod h1:C8Q/3pNHT4RE9e4rYR9PHeS6KPMlStRBgYrJQJNy/vA= 277 | github.com/siderolabs/go-retry v0.3.3 h1:zKV+S1vumtO72E6sYsLlmIdV/G/GcYSBLiEx/c9oCEg= 278 | github.com/siderolabs/go-retry v0.3.3/go.mod h1:Ff/VGc7v7un4uQg3DybgrmOWHEmJ8BzZds/XNn/BqMI= 279 | github.com/siderolabs/image-factory v0.8.4 h1:fVC85y8fBAnZLxSkA9eHzzH+yf48Gyd7eaxWz+vljqE= 280 | github.com/siderolabs/image-factory v0.8.4/go.mod h1:CJd8CHVkaggfzHvwP+TXuwe+yyH94rEazf/RBfARrCE= 281 | github.com/siderolabs/net v0.4.0 h1:1bOgVay/ijPkJz4qct98nHsiB/ysLQU0KLoBC4qLm7I= 282 | github.com/siderolabs/net v0.4.0/go.mod h1:/ibG+Hm9HU27agp5r9Q3eZicEfjquzNzQNux5uEk0kM= 283 | github.com/siderolabs/omni/client v1.3.0-beta.1.0.20251106113647-e38f0ffe52b0 h1:730Ef1u6eFtJ8c6joZAcsK3QGFsl4GaYHuo7IZyaOcI= 284 | github.com/siderolabs/omni/client v1.3.0-beta.1.0.20251106113647-e38f0ffe52b0/go.mod h1:3E2pC3cf8CFlKL2EOKk/53refryZgcg4H3EmlBtbLqQ= 285 | github.com/siderolabs/proto-codec v0.1.2 h1:KYrRiCk5wdA2ilZZoW4bWtICCF4y3r28FhmunPa50HE= 286 | github.com/siderolabs/proto-codec v0.1.2/go.mod h1:TCsjpw732TWuOx4Vd4gYhivPOttEhdPvczLfMQ6Y9Dc= 287 | github.com/siderolabs/protoenc v0.2.4 h1:D3Fpn2nQSQOhl8ZlAxijZAf7K6F8CM1uZq0afIGsr8Q= 288 | github.com/siderolabs/protoenc v0.2.4/go.mod h1:i5XLHjfv5vyi7LhQrSEo19HCA+lYtDd7CWxsoWp9XE8= 289 | github.com/siderolabs/siderolink v0.3.15 h1:WSsgKQGJY/ObIKjTcYYGEaGfRMyox+r/Ft+9lIgJqOI= 290 | github.com/siderolabs/siderolink v0.3.15/go.mod h1:iWdlsHji90zotgDg4+a2zJL2ZMNJckQ8/VwqR39ThBM= 291 | github.com/siderolabs/talos/pkg/machinery v1.12.0-alpha.2.0.20251104112157-92eeaa4826cf h1:UVyr8c5Ee1RbGRE4aAAgi89ulJlHTvXtcoaYU5oEbwM= 292 | github.com/siderolabs/talos/pkg/machinery v1.12.0-alpha.2.0.20251104112157-92eeaa4826cf/go.mod h1:n2aIyxoNdNXE46hSp4V2w2R6rVzWC2K+9I2PsutRjT8= 293 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 294 | github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= 295 | github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= 296 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 297 | github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 298 | github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= 299 | github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 300 | github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= 301 | github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs= 302 | github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= 303 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 304 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 305 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 306 | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= 307 | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 308 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 309 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 310 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 311 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 312 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 313 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 314 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 315 | github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 316 | github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 317 | github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= 318 | github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= 319 | github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 320 | github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= 321 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 322 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 323 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 324 | github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 325 | github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 326 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 327 | go.opentelemetry.io/auto/sdk v1.2.0 h1:YpRtUFjvhSymycLS2T81lT6IGhcUP+LUPtv0iv1N8bM= 328 | go.opentelemetry.io/auto/sdk v1.2.0/go.mod h1:1deq2zL7rwjwC8mR7XgY2N+tlIl6pjmEUoLDENMEzwk= 329 | go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= 330 | go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= 331 | go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= 332 | go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= 333 | go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= 334 | go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= 335 | go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= 336 | go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= 337 | go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= 338 | go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= 339 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 340 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 341 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 342 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 343 | go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= 344 | go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 345 | go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= 346 | go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= 347 | go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= 348 | go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= 349 | go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s= 350 | go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= 351 | go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= 352 | go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= 353 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 354 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 355 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 356 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 357 | golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= 358 | golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= 359 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 360 | golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b h1:18qgiDvlvH7kk8Ioa8Ov+K6xCi0GMvmGfGW0sgd/SYA= 361 | golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= 362 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 363 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 364 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 365 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 366 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 367 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 368 | golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 369 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 370 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 371 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 372 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 373 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 374 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 375 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 376 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 377 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 378 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 379 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 380 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 381 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 382 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 383 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 384 | golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= 385 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 386 | golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 387 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 388 | golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 389 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 390 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 391 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 392 | golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= 393 | golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= 394 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 395 | golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= 396 | golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= 397 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 398 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 399 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 400 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 401 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 402 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 403 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 404 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 405 | golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= 406 | golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 407 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 408 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 409 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 410 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 411 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 412 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 413 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 414 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 415 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 416 | golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 417 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 418 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 419 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 420 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 421 | golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 422 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 423 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 424 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 425 | golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 426 | golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 427 | golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 428 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 429 | golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 430 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 431 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 432 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 433 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 434 | golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= 435 | golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 436 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 437 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 438 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 439 | golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= 440 | golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= 441 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 442 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 443 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 444 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 445 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 446 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 447 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 448 | golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 449 | golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= 450 | golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= 451 | golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= 452 | golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= 453 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 454 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 455 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 456 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 457 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 458 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 459 | golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 460 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 461 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 462 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 463 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 464 | golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= 465 | golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= 466 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 467 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 468 | golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= 469 | golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= 470 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 471 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 472 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 473 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 474 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= 475 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= 476 | golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A= 477 | golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw= 478 | golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU= 479 | golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ= 480 | gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= 481 | gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= 482 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 483 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 484 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 485 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 486 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 487 | google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 488 | google.golang.org/genproto/googleapis/api v0.0.0-20251020155222-88f65dc88635 h1:1wvBeYv+A2zfEbxROscJl69OP0m74S8wGEO+Syat26o= 489 | google.golang.org/genproto/googleapis/api v0.0.0-20251020155222-88f65dc88635/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= 490 | google.golang.org/genproto/googleapis/rpc v0.0.0-20251020155222-88f65dc88635 h1:3uycTxukehWrxH4HtPRtn1PDABTU331ViDjyqrUbaog= 491 | google.golang.org/genproto/googleapis/rpc v0.0.0-20251020155222-88f65dc88635/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= 492 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 493 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 494 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 495 | google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= 496 | google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= 497 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 498 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 499 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 500 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 501 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 502 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 503 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 504 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 505 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 506 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 507 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 508 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 509 | google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= 510 | google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 511 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 512 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 513 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 514 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 515 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 516 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 517 | gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= 518 | gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= 519 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 520 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 521 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 522 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 523 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 524 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 525 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 526 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 527 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 528 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 529 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 530 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 531 | gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 532 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 533 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 534 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 535 | gvisor.dev/gvisor v0.0.0-20250503011706-39ed1f5ac29c h1:m/r7OM+Y2Ty1sgBQ7Qb27VgIMBW8ZZhT4gLnUyDIhzI= 536 | gvisor.dev/gvisor v0.0.0-20250503011706-39ed1f5ac29c/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g= 537 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 538 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 539 | k8s.io/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ= 540 | k8s.io/api v0.35.0-alpha.1 h1:aL5Q6ZV4MQ2NZMmlnAsV7wj9a30gLhlLnGbx6GUmuBs= 541 | k8s.io/api v0.35.0-alpha.1/go.mod h1:BoZqpN+rs1nX+WI4b+iOCpHIAZT1A5Cx29nfk4Kn4DY= 542 | k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= 543 | k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= 544 | k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= 545 | k8s.io/apimachinery v0.35.0-alpha.1 h1:FZCO78xXJf7Bb7oLzw5p6nakz/SWaGTi4+IaOl7uAYk= 546 | k8s.io/apimachinery v0.35.0-alpha.1/go.mod h1:1YSL0XujdSTcnuHOR73D16EdW+d49JOdd8TXjCo6Dhc= 547 | k8s.io/client-go v0.35.0-alpha.1 h1:DbQuaoETvFkhWfIckZj3hj1iNnBvEIdiWjSlosmtlX4= 548 | k8s.io/client-go v0.35.0-alpha.1/go.mod h1:CI5Ggq6AukXNEBV2UeBgY4tfrOZfDSa7KuoWwLfHqGA= 549 | k8s.io/code-generator v0.23.3/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk= 550 | k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= 551 | k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= 552 | k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= 553 | k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= 554 | k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= 555 | k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= 556 | k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= 557 | k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 558 | k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= 559 | k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= 560 | k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= 561 | k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= 562 | k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 563 | k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 564 | k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= 565 | k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 566 | kubevirt.io/api v1.5.2 h1:ugul5yJOmvXRIHH0IUwU2FKMnENvGUCqfBKPDZ4chFA= 567 | kubevirt.io/api v1.5.2/go.mod h1:B6OBbPKntPHOOtoxyRk5YKJHekWWOiwZDb2XncitcJ0= 568 | kubevirt.io/containerized-data-importer-api v1.62.0 h1:gu8s/H1qJ40xpFH+B4Hr1X6W22IbzazOXHvRAUwrESw= 569 | kubevirt.io/containerized-data-importer-api v1.62.0/go.mod h1:VGp35wxpLXU18b7cnEpmcThI3AjcZUSfg/Zfql44U4o= 570 | kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4 h1:fZYvD3/Vnitfkx6IJxjLAk8ugnZQ7CXVYcRfkSKmuZY= 571 | kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= 572 | sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= 573 | sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= 574 | sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= 575 | sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= 576 | sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= 577 | sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= 578 | sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= 579 | sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= 580 | sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= 581 | sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= 582 | sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= 583 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= 584 | sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= 585 | sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= 586 | sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= 587 | --------------------------------------------------------------------------------