From c77cb7c812105620efc05c1794f4d19021cd0f60 Mon Sep 17 00:00:00 2001 From: Ygal Blum Date: Thu, 23 Jun 2022 12:23:26 +0300 Subject: [PATCH] OSBuildEnvConfig Controller - Create and Setup Workers Controller ---------- Create ConfigMaps for Ansible configuration and playbook Create ConfigMap for the osbuild-worker Create Secret with SSH Key-Pair if needed For each VM: - If needed, create the VM and expose its SSH port as a service - Create certificate - Create ConfigMap for the inventory - Create the Setup Job Remove the worker certificate secrets on teardown main.go ------- Add kubevirt v1 to Scheme Create Job and VM repositories Templates --------- Add templates for: - Worker VM - Worker Setup Job - OSBuild-Worker configuration - Ansible Config - Ansible Inventory - Ansible Playbook Repository ---------- Add repositories for Job and CNV VM RBAC ---- Add permissions for Jobs and CNV VMs SSHKey ------ Add package for SSH Key-Pair generation Setup Container image --------------------- Add Dockerfile Add Makefile rules Add ansible requirements.yml file Type ---- Add comment about the required key in the CABundle secret Config ------ Add configuration flags for the worker setup container image name and tag Add configuration flags for the composer api service container image name and tag Add configuration flags for the envoy proxy container image name and tag Add configuration flags for the OSBuild and OSBuild-Composer release tags Unit Tests ---------- Add tests to the new code Sample ------ Rename the worker to avoid conflict with node Add caBundleSecretReference Signed-off-by: Ygal Blum --- Dockerfile.WorkerSetupJob | 19 + Makefile | 13 + api/v1alpha1/osbuildenvconfig_types.go | 1 + ...r.project-flotta.io_osbuildenvconfigs.yaml | 2 +- config/rbac/role.yaml | 24 + .../osbuilder_v1alpha1_osbuildenvconfig.yaml | 4 +- controllers/osbuildenvconfig_controller.go | 625 +- .../osbuildenvconfig_controller_test.go | 197 +- go.mod | 11 +- go.sum | 29 +- internal/conf/config.go | 24 + internal/repository/job/job.go | 34 + internal/repository/job/mock_job.go | 65 + .../virtualmachine/mock_virtualmachine.go | 65 + .../virtualmachine/virtualmachine.go | 34 + internal/sshkey/sshkey.go | 71 + main.go | 9 + resources/ansible/requirements.yml | 2 + .../templates/composer-proxy-config.yaml | 1 + .../worker-config-ansible-config.cfg | 4 + .../worker-config-ansible-inventory.yaml | 6 + .../worker-config-ansible-playbook.yaml | 166 + .../worker-osbuild-worker-config.toml | 19 + resources/templates/worker-setup-job.yaml | 65 + resources/templates/worker-vm.yaml | 95 + .../openshift/custom-resource-status/LICENSE | 201 + .../conditions/v1/conditions.go | 104 + .../conditions/v1/doc.go | 9 + .../conditions/v1/types.go | 51 + .../conditions/v1/zz_generated.deepcopy.go | 23 + vendor/github.com/pborman/uuid/.travis.yml | 10 + .../github.com/pborman/uuid/CONTRIBUTING.md | 10 + vendor/github.com/pborman/uuid/CONTRIBUTORS | 1 + vendor/github.com/pborman/uuid/LICENSE | 27 + vendor/github.com/pborman/uuid/README.md | 15 + vendor/github.com/pborman/uuid/dce.go | 84 + vendor/github.com/pborman/uuid/doc.go | 13 + vendor/github.com/pborman/uuid/hash.go | 53 + vendor/github.com/pborman/uuid/marshal.go | 85 + vendor/github.com/pborman/uuid/node.go | 50 + vendor/github.com/pborman/uuid/sql.go | 68 + vendor/github.com/pborman/uuid/time.go | 57 + vendor/github.com/pborman/uuid/util.go | 32 + vendor/github.com/pborman/uuid/uuid.go | 162 + vendor/github.com/pborman/uuid/version1.go | 23 + vendor/github.com/pborman/uuid/version4.go | 26 + vendor/golang.org/x/crypto/blowfish/block.go | 159 + vendor/golang.org/x/crypto/blowfish/cipher.go | 99 + vendor/golang.org/x/crypto/blowfish/const.go | 199 + .../x/crypto/chacha20/chacha_arm64.go | 17 + .../x/crypto/chacha20/chacha_arm64.s | 308 + .../x/crypto/chacha20/chacha_generic.go | 398 ++ .../x/crypto/chacha20/chacha_noasm.go | 14 + .../x/crypto/chacha20/chacha_ppc64le.go | 17 + .../x/crypto/chacha20/chacha_ppc64le.s | 450 ++ .../x/crypto/chacha20/chacha_s390x.go | 28 + .../x/crypto/chacha20/chacha_s390x.s | 225 + vendor/golang.org/x/crypto/chacha20/xor.go | 42 + .../x/crypto/curve25519/curve25519.go | 146 + .../x/crypto/curve25519/internal/field/README | 7 + .../x/crypto/curve25519/internal/field/fe.go | 416 ++ .../curve25519/internal/field/fe_amd64.go | 16 + .../curve25519/internal/field/fe_amd64.s | 379 ++ .../internal/field/fe_amd64_noasm.go | 12 + .../curve25519/internal/field/fe_arm64.go | 16 + .../curve25519/internal/field/fe_arm64.s | 43 + .../internal/field/fe_arm64_noasm.go | 12 + .../curve25519/internal/field/fe_generic.go | 264 + .../curve25519/internal/field/sync.checkpoint | 1 + .../crypto/curve25519/internal/field/sync.sh | 19 + vendor/golang.org/x/crypto/ed25519/ed25519.go | 71 + .../x/crypto/internal/poly1305/bits_compat.go | 40 + .../x/crypto/internal/poly1305/bits_go1.13.go | 22 + .../x/crypto/internal/poly1305/mac_noasm.go | 10 + .../x/crypto/internal/poly1305/poly1305.go | 99 + .../x/crypto/internal/poly1305/sum_amd64.go | 48 + .../x/crypto/internal/poly1305/sum_amd64.s | 109 + .../x/crypto/internal/poly1305/sum_generic.go | 309 + .../x/crypto/internal/poly1305/sum_ppc64le.go | 48 + .../x/crypto/internal/poly1305/sum_ppc64le.s | 182 + .../x/crypto/internal/poly1305/sum_s390x.go | 77 + .../x/crypto/internal/poly1305/sum_s390x.s | 504 ++ .../x/crypto/internal/subtle/aliasing.go | 33 + .../crypto/internal/subtle/aliasing_purego.go | 36 + vendor/golang.org/x/crypto/ssh/buffer.go | 97 + vendor/golang.org/x/crypto/ssh/certs.go | 589 ++ vendor/golang.org/x/crypto/ssh/channel.go | 633 ++ vendor/golang.org/x/crypto/ssh/cipher.go | 789 +++ vendor/golang.org/x/crypto/ssh/client.go | 282 + vendor/golang.org/x/crypto/ssh/client_auth.go | 725 +++ vendor/golang.org/x/crypto/ssh/common.go | 430 ++ vendor/golang.org/x/crypto/ssh/connection.go | 143 + vendor/golang.org/x/crypto/ssh/doc.go | 22 + vendor/golang.org/x/crypto/ssh/handshake.go | 704 +++ .../ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go | 93 + vendor/golang.org/x/crypto/ssh/kex.go | 774 +++ vendor/golang.org/x/crypto/ssh/keys.go | 1447 +++++ vendor/golang.org/x/crypto/ssh/mac.go | 61 + vendor/golang.org/x/crypto/ssh/messages.go | 877 +++ vendor/golang.org/x/crypto/ssh/mux.go | 351 ++ vendor/golang.org/x/crypto/ssh/server.go | 752 +++ vendor/golang.org/x/crypto/ssh/session.go | 648 +++ vendor/golang.org/x/crypto/ssh/ssh_gss.go | 139 + vendor/golang.org/x/crypto/ssh/streamlocal.go | 116 + vendor/golang.org/x/crypto/ssh/tcpip.go | 474 ++ vendor/golang.org/x/crypto/ssh/transport.go | 357 ++ vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s | 18 + vendor/golang.org/x/sys/cpu/byteorder.go | 66 + vendor/golang.org/x/sys/cpu/cpu.go | 287 + vendor/golang.org/x/sys/cpu/cpu_aix.go | 34 + vendor/golang.org/x/sys/cpu/cpu_arm.go | 73 + vendor/golang.org/x/sys/cpu/cpu_arm64.go | 172 + vendor/golang.org/x/sys/cpu/cpu_arm64.s | 32 + vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go | 12 + vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go | 22 + vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 17 + .../golang.org/x/sys/cpu/cpu_gccgo_arm64.go | 12 + .../golang.org/x/sys/cpu/cpu_gccgo_s390x.go | 23 + vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c | 43 + vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go | 33 + vendor/golang.org/x/sys/cpu/cpu_linux.go | 16 + vendor/golang.org/x/sys/cpu/cpu_linux_arm.go | 39 + .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 71 + .../golang.org/x/sys/cpu/cpu_linux_mips64x.go | 24 + .../golang.org/x/sys/cpu/cpu_linux_noinit.go | 10 + .../golang.org/x/sys/cpu/cpu_linux_ppc64x.go | 32 + .../golang.org/x/sys/cpu/cpu_linux_s390x.go | 40 + vendor/golang.org/x/sys/cpu/cpu_loong64.go | 13 + vendor/golang.org/x/sys/cpu/cpu_mips64x.go | 16 + vendor/golang.org/x/sys/cpu/cpu_mipsx.go | 12 + .../golang.org/x/sys/cpu/cpu_netbsd_arm64.go | 173 + vendor/golang.org/x/sys/cpu/cpu_other_arm.go | 10 + .../golang.org/x/sys/cpu/cpu_other_arm64.go | 10 + .../golang.org/x/sys/cpu/cpu_other_mips64x.go | 13 + vendor/golang.org/x/sys/cpu/cpu_ppc64x.go | 17 + vendor/golang.org/x/sys/cpu/cpu_riscv64.go | 12 + vendor/golang.org/x/sys/cpu/cpu_s390x.go | 172 + vendor/golang.org/x/sys/cpu/cpu_s390x.s | 58 + vendor/golang.org/x/sys/cpu/cpu_wasm.go | 18 + vendor/golang.org/x/sys/cpu/cpu_x86.go | 145 + vendor/golang.org/x/sys/cpu/cpu_x86.s | 28 + vendor/golang.org/x/sys/cpu/cpu_zos.go | 10 + vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go | 25 + vendor/golang.org/x/sys/cpu/hwcap_linux.go | 56 + .../golang.org/x/sys/cpu/syscall_aix_gccgo.go | 27 + .../x/sys/cpu/syscall_aix_ppc64_gc.go | 36 + vendor/kubevirt.io/api/LICENSE | 202 + vendor/kubevirt.io/api/core/register.go | 4 + .../api/core/v1/componentconfig.go | 48 + .../api/core/v1/deepcopy_generated.go | 5087 +++++++++++++++++ vendor/kubevirt.io/api/core/v1/defaults.go | 241 + vendor/kubevirt.io/api/core/v1/doc.go | 8 + vendor/kubevirt.io/api/core/v1/register.go | 121 + vendor/kubevirt.io/api/core/v1/sanitizers.go | 45 + vendor/kubevirt.io/api/core/v1/schema.go | 1407 +++++ .../api/core/v1/schema_swagger_generated.go | 805 +++ vendor/kubevirt.io/api/core/v1/types.go | 2315 ++++++++ .../api/core/v1/types_swagger_generated.go | 776 +++ .../api/core/v1/zz_generated.defaults.go | 566 ++ .../containerized-data-importer-api/LICENSE | 202 + .../pkg/apis/core/register.go | 6 + .../pkg/apis/core/v1beta1/doc.go | 6 + .../pkg/apis/core/v1beta1/register.go | 54 + .../pkg/apis/core/v1beta1/types.go | 801 +++ .../core/v1beta1/types_swagger_generated.go | 395 ++ .../pkg/apis/core/v1beta1/types_transfer.go | 134 + .../pkg/apis/core/v1beta1/utils.go | 61 + .../core/v1beta1/zz_generated.deepcopy.go | 1517 +++++ .../api/LICENSE | 201 + .../api/types.go | 130 + vendor/modules.txt | 29 +- 171 files changed, 35097 insertions(+), 58 deletions(-) create mode 100644 Dockerfile.WorkerSetupJob create mode 100644 internal/repository/job/job.go create mode 100644 internal/repository/job/mock_job.go create mode 100644 internal/repository/virtualmachine/mock_virtualmachine.go create mode 100644 internal/repository/virtualmachine/virtualmachine.go create mode 100644 internal/sshkey/sshkey.go create mode 100644 resources/ansible/requirements.yml create mode 100644 resources/templates/worker-config-ansible-config.cfg create mode 100644 resources/templates/worker-config-ansible-inventory.yaml create mode 100644 resources/templates/worker-config-ansible-playbook.yaml create mode 100644 resources/templates/worker-osbuild-worker-config.toml create mode 100644 resources/templates/worker-setup-job.yaml create mode 100644 resources/templates/worker-vm.yaml create mode 100644 vendor/github.com/openshift/custom-resource-status/LICENSE create mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go create mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go create mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go create mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/pborman/uuid/.travis.yml create mode 100644 vendor/github.com/pborman/uuid/CONTRIBUTING.md create mode 100644 vendor/github.com/pborman/uuid/CONTRIBUTORS create mode 100644 vendor/github.com/pborman/uuid/LICENSE create mode 100644 vendor/github.com/pborman/uuid/README.md create mode 100644 vendor/github.com/pborman/uuid/dce.go create mode 100644 vendor/github.com/pborman/uuid/doc.go create mode 100644 vendor/github.com/pborman/uuid/hash.go create mode 100644 vendor/github.com/pborman/uuid/marshal.go create mode 100644 vendor/github.com/pborman/uuid/node.go create mode 100644 vendor/github.com/pborman/uuid/sql.go create mode 100644 vendor/github.com/pborman/uuid/time.go create mode 100644 vendor/github.com/pborman/uuid/util.go create mode 100644 vendor/github.com/pborman/uuid/uuid.go create mode 100644 vendor/github.com/pborman/uuid/version1.go create mode 100644 vendor/github.com/pborman/uuid/version4.go create mode 100644 vendor/golang.org/x/crypto/blowfish/block.go create mode 100644 vendor/golang.org/x/crypto/blowfish/cipher.go create mode 100644 vendor/golang.org/x/crypto/blowfish/const.go create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_arm64.go create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_arm64.s create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_generic.go create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_noasm.go create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_s390x.go create mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_s390x.s create mode 100644 vendor/golang.org/x/crypto/chacha20/xor.go create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/README create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh create mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/poly1305.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go create mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing.go create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go create mode 100644 vendor/golang.org/x/crypto/ssh/buffer.go create mode 100644 vendor/golang.org/x/crypto/ssh/certs.go create mode 100644 vendor/golang.org/x/crypto/ssh/channel.go create mode 100644 vendor/golang.org/x/crypto/ssh/cipher.go create mode 100644 vendor/golang.org/x/crypto/ssh/client.go create mode 100644 vendor/golang.org/x/crypto/ssh/client_auth.go create mode 100644 vendor/golang.org/x/crypto/ssh/common.go create mode 100644 vendor/golang.org/x/crypto/ssh/connection.go create mode 100644 vendor/golang.org/x/crypto/ssh/doc.go create mode 100644 vendor/golang.org/x/crypto/ssh/handshake.go create mode 100644 vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go create mode 100644 vendor/golang.org/x/crypto/ssh/kex.go create mode 100644 vendor/golang.org/x/crypto/ssh/keys.go create mode 100644 vendor/golang.org/x/crypto/ssh/mac.go create mode 100644 vendor/golang.org/x/crypto/ssh/messages.go create mode 100644 vendor/golang.org/x/crypto/ssh/mux.go create mode 100644 vendor/golang.org/x/crypto/ssh/server.go create mode 100644 vendor/golang.org/x/crypto/ssh/session.go create mode 100644 vendor/golang.org/x/crypto/ssh/ssh_gss.go create mode 100644 vendor/golang.org/x/crypto/ssh/streamlocal.go create mode 100644 vendor/golang.org/x/crypto/ssh/tcpip.go create mode 100644 vendor/golang.org/x/crypto/ssh/transport.go create mode 100644 vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s create mode 100644 vendor/golang.org/x/sys/cpu/byteorder.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_aix.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.s create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_loong64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_mips64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_mipsx.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_arm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_ppc64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_riscv64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.s create mode 100644 vendor/golang.org/x/sys/cpu/cpu_wasm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.s create mode 100644 vendor/golang.org/x/sys/cpu/cpu_zos.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/hwcap_linux.go create mode 100644 vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go create mode 100644 vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go create mode 100644 vendor/kubevirt.io/api/LICENSE create mode 100644 vendor/kubevirt.io/api/core/register.go create mode 100644 vendor/kubevirt.io/api/core/v1/componentconfig.go create mode 100644 vendor/kubevirt.io/api/core/v1/deepcopy_generated.go create mode 100644 vendor/kubevirt.io/api/core/v1/defaults.go create mode 100644 vendor/kubevirt.io/api/core/v1/doc.go create mode 100644 vendor/kubevirt.io/api/core/v1/register.go create mode 100644 vendor/kubevirt.io/api/core/v1/sanitizers.go create mode 100644 vendor/kubevirt.io/api/core/v1/schema.go create mode 100644 vendor/kubevirt.io/api/core/v1/schema_swagger_generated.go create mode 100644 vendor/kubevirt.io/api/core/v1/types.go create mode 100644 vendor/kubevirt.io/api/core/v1/types_swagger_generated.go create mode 100644 vendor/kubevirt.io/api/core/v1/zz_generated.defaults.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/LICENSE create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/register.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/doc.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/register.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_transfer.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/utils.go create mode 100644 vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go create mode 100644 vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/LICENSE create mode 100644 vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/types.go diff --git a/Dockerfile.WorkerSetupJob b/Dockerfile.WorkerSetupJob new file mode 100644 index 00000000..3e97169a --- /dev/null +++ b/Dockerfile.WorkerSetupJob @@ -0,0 +1,19 @@ +FROM registry.access.redhat.com/ubi8/python-39 + +USER 0 + +COPY resources/ansible/requirements.yml /tmp/requirements.yml + +RUN dnf install skopeo -y && \ + pip install --upgrade pip && \ + pip install openshift && \ + pip install jmespath && \ + pip install netaddr && \ + pip install ansible==2.9.27 && \ + curl -L https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux.tar.gz | \ + tar -xvzf - -C /usr/local/bin/ oc && chmod 755 /usr/local/bin/oc && ln -s /usr/local/bin/oc /usr/local/bin/kubectl && \ + ansible-galaxy collection install -r /tmp/requirements.yml + +RUN chgrp -R 0 $HOME && chmod -R g=u $HOME + +USER 1001 diff --git a/Makefile b/Makefile index 8b487da7..73fe1c1c 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,11 @@ endif # Image URL to use all building/pushing image targets IMG ?= controller:latest + +# Worker setup job container +SETUP_IMG ?= quay.io/project-flotta/osbuild-operator-worker-setup:v0.1 +SETUP_DOCKERFILE = Dockerfile.WorkerSetupJob + # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. ENVTEST_K8S_VERSION = 1.23 @@ -203,6 +208,14 @@ docker-build: test ## Build docker image with the manager. docker-push: ## Push docker image with the manager. $(CONTAINER_RUNTIME) push ${IMG} +.PHONY: setup-image-build +setup-image-build: # Build container image for the Worker setup job + $(CONTAINER_RUNTIME) build -t ${SETUP_IMG} -f ${SETUP_DOCKERFILE} . + +.PHONY: setup-image-push +setup-image-push: ## Push the Worker setup job image. + $(CONTAINER_RUNTIME) push ${SETUP_IMG} + ##@ Deployment ifndef ignore-not-found diff --git a/api/v1alpha1/osbuildenvconfig_types.go b/api/v1alpha1/osbuildenvconfig_types.go index 12bf2e7f..f5817d10 100644 --- a/api/v1alpha1/osbuildenvconfig_types.go +++ b/api/v1alpha1/osbuildenvconfig_types.go @@ -138,6 +138,7 @@ type GenericS3ServiceConfig struct { Endpoint string `json:"endpoint"` // CABundleSecretReference is a reference to a secret in the same namespace, // containing the CA certificate to use when connecting to the S3 service (optional, default empty) + // If provided the required key is ca-bundle // +kubebuilder:validation:Optional CABundleSecretReference *buildv1.SecretLocalReference `json:"caBundleSecretReference,omitempty"` // SkipSSLVerification when set to true the SSL certificate will not be verified (optional, default False) diff --git a/config/crd/bases/osbuilder.project-flotta.io_osbuildenvconfigs.yaml b/config/crd/bases/osbuilder.project-flotta.io_osbuildenvconfigs.yaml index 24852521..75f21c31 100644 --- a/config/crd/bases/osbuilder.project-flotta.io_osbuildenvconfigs.yaml +++ b/config/crd/bases/osbuilder.project-flotta.io_osbuildenvconfigs.yaml @@ -128,7 +128,7 @@ spec: description: CABundleSecretReference is a reference to a secret in the same namespace, containing the CA certificate to use when connecting to the S3 service (optional, default - empty) + empty) If provided the required key is ca-bundle properties: name: description: Name is the name of the resource in the same diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 1c19b302..051bbe6a 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -17,6 +17,18 @@ rules: - patch - update - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - cert-manager.io resources: @@ -65,6 +77,18 @@ rules: - patch - update - watch +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - osbuilder.project-flotta.io resources: diff --git a/config/samples/osbuilder_v1alpha1_osbuildenvconfig.yaml b/config/samples/osbuilder_v1alpha1_osbuildenvconfig.yaml index e2be6826..7379708b 100644 --- a/config/samples/osbuilder_v1alpha1_osbuildenvconfig.yaml +++ b/config/samples/osbuilder_v1alpha1_osbuildenvconfig.yaml @@ -9,7 +9,7 @@ spec: name: composer-db sslMode: disable workers: - - name: worker-1 + - name: builder-1 vmWorkerConfig: architecture: x86_64 imageURL: "http://nexus-osbuild:8081/repository/disk-images/rhel-8.5-x86_64-kvm.qcow2" @@ -19,6 +19,8 @@ spec: genericS3ServiceConfig: credsSecretReference: name: osbuild-s3-credentials + caBundleSecretReference: + name: osbuild-s3-ca-bundle region: us-east-1 bucket: osbuild-images endpoint: "http://minio:9000" diff --git a/controllers/osbuildenvconfig_controller.go b/controllers/osbuildenvconfig_controller.go index 45d9edad..bc32af3e 100644 --- a/controllers/osbuildenvconfig_controller.go +++ b/controllers/osbuildenvconfig_controller.go @@ -19,13 +19,16 @@ package controllers import ( "context" "fmt" + "path" "time" appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" @@ -34,6 +37,9 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certmanagermetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + + kubevirtv1 "kubevirt.io/api/core/v1" + "github.com/go-logr/logr" osbuildv1alpha1 "github.com/project-flotta/osbuild-operator/api/v1alpha1" @@ -41,9 +47,12 @@ import ( "github.com/project-flotta/osbuild-operator/internal/repository/certificate" "github.com/project-flotta/osbuild-operator/internal/repository/configmap" "github.com/project-flotta/osbuild-operator/internal/repository/deployment" + "github.com/project-flotta/osbuild-operator/internal/repository/job" "github.com/project-flotta/osbuild-operator/internal/repository/osbuildenvconfig" "github.com/project-flotta/osbuild-operator/internal/repository/secret" "github.com/project-flotta/osbuild-operator/internal/repository/service" + "github.com/project-flotta/osbuild-operator/internal/repository/virtualmachine" + "github.com/project-flotta/osbuild-operator/internal/sshkey" "github.com/project-flotta/osbuild-operator/internal/templates" ) @@ -76,20 +85,81 @@ const ( composerDeploymentName = "composer" composerDeploymentTemplateFile = "composer-deployment.yaml" - composerImageName = "quay.io/app-sre/composer" - composerImageTag = "fc87b17" - - envoyProxyImageName = "docker.io/envoyproxy/envoy" - envoyProxyImageTag = "v1.21-latest" - composerAPIInternalPort = 18080 composerAPIExternalPort = 8080 workerAPIInternalPort = 18700 workerAPIExternalPort = 8700 + composerWorkerRequestJobTimeout = time.Second * 20 + envoyProxyCertsDir = "/etc/certs" + + workerSSHKeysSecretName = "osbuild-worker-ssh" // #nosec G101 + workerSSHKeysPrivateKeyKey = "ssh-privatekey" + workerSSHKeysPublicKeyKey = "ssh-publickey" + + workerVMUsername = "cloud-user" + workerVMTemplateFile = "worker-vm.yaml" + + workerSSHServiceNameFormat = "worker-%s-ssh" + workerSSHPortName = "ssh" + + workerCertificateNameFormat = "worker-%s-cert" + + workerSetupPlaybookConfigMapName = "osbuild-worker-setup-playbook" + workerSetupPlaybookConfigMapKey = "playbook.yaml" + workerSetupPlaybookTemplateFile = "worker-config-ansible-playbook.yaml" + + workerRPMRepoDistribution = "rhel-8-cdn" + workerRHCredentialsDir = "/var/secrets/redhat-portal-credentials" // #nosec G101 + workerRHCredentialsUsernameKey = "username" + workerRHCredentialsPasswordKey = "password" + workerOSBuildWorkerCertsDir = "/var/secrets/osbuild-worker-certs" + + workerSetupAnsibleConfigConfigMapName = "osbuild-worker-setup-ansible-config" + workerSetupAnsibleConfigConfigMapKey = "ansible.cfg" + workerSetupAnsibleConfigTemplateFile = "worker-config-ansible-config.cfg" + + workerSetupInventoryConfigMapNameFormat = "worker-%s-inventory" + workerSetupInventoryConfigMapKey = "inventory.yaml" + workerSetupInventoryTemplateFile = "worker-config-ansible-inventory.yaml" + + workerOSBuildWorkerConfigConfigMapName = "osbuild-worker-config" + workerOSBuildWorkerConfigConfigMapKey = "osbuild-worker.toml" + workerOSBuildWorkerConfigTemplateFile = "worker-osbuild-worker-config.toml" + workerOSBuildWorkerConfigDir = "/var/config" + workerOSBuildWorkerConfigS3CredentialsFile = "s3-creds" + workerOSBuildWorkerConfigS3CABundleFile = "s3-cabundle" + + workerOSBuildWorkerS3CredsDir = "/var/secrets/osbuild-s3-certs" // #nosec G101 + workerOSBuildWorkerS3CABundleDir = "/var/secrets/osbuild-s3-ca-bundle" + + workerOSBuildWorkerS3CredsAccessKeyIDKey = "access-key-id" + workerOSBuildWorkerS3CredsSecretAccessKeyKey = "secret-access-key" + workerOSBuildWorkerS3CABundleKey = "ca-bundle" + + workerSetupJobSSHKeyDir = "/var/secrets/ssh" + + workerSetupJobTemplateFile = "worker-setup-job.yaml" + + workerSetupJobNameFormat = "worker-%s-setup" ) +type composerConfigParametersKoji struct { + LogLevel string +} + +type composerConfigParametersWorker struct { + LogLevel string + RequestJobTimeout string + BasePath string +} + +type composerConfigParameters struct { + Koji composerConfigParametersKoji + Worker composerConfigParametersWorker +} + // composerDeploymentParameters includes all the parameters needed to render the Composer Proxy Config and Deployment type composerDeploymentParameters struct { ComposerDeploymentNamespace string @@ -111,6 +181,78 @@ type composerDeploymentParameters struct { ComposerCertsSecretPrivateKeyKey string ComposerCertsSecretCACertKey string ProxyConfigMapName string + ProxyWorkerAPIUpstreamTimeout string +} + +type workerSetupPlaybookParameters struct { + RPMRepoDistribution string + OSBuildComposerTag string + OSBuildTag string + RHCredentialsDir string + RHCredentialsUsernameKey string + RHCredentialsPasswordKey string + OSBuildWorkerCertsDir string + ComposerWorkerAPIServiceName string + OSBuildWorkerConfigDir string + OSBuildWorkerConfigFile string + OSBuildWorkerS3CredsFile string + OSBuildWorkerS3CredsDir string + OSBuildWorkerS3CredsAccessKeyIDKey string + OSBuildWorkerS3CredsSecretAccessKeyKey string + OSBuildWorkerS3CABundleFile string + OSBuildWorkerS3CABundleDir string + OSBuildWorkerS3CABundleKey string +} + +type workerSetupInventoryParameters struct { + Address string + User string + SSHKey string +} + +type workerVMParameters struct { + Namespace string + Name string + ImageURL string + Hostname string + Username string + SSHKeysSecretName string +} + +type workerOSBuildWorkerConfigParametersGenericS3 struct { + Region string + Endpoint string + CABundleFile *string + SkipSSLVerification *bool +} + +type workerOSBuildWorkerConfigParameters struct { + CredentialsFile string + Bucket string + GenericS3 *workerOSBuildWorkerConfigParametersGenericS3 +} + +type workerSetupJobParameters struct { + WorkerConfigJobNamespace string + WorkerConfigJobName string + WorkerConfigJobImageName string + WorkerConfigJobImageTag string + WorkerConfigAnsibleConfigConfigMapKey string + WorkerConfigInventoryConfigMapKey string + WorkerConfigPlaybookConfigMapKey string + WorkerConfigJobSSHKeyDir string + RHCredentialsDir string + OSBuildWorkerCertsDir string + WorkerSSHKeysSecretName string + WorkerConfigAnsibleConfigConfigMapName string + WorkerConfigPlaybookConfigMapName string + WorkerConfigInventoryConfigMapName string + RedHatCredsSecretName string + WorkerCertificateName string + WorkerOSBuildWorkerConfigConfigMapName string + OSBuildWorkerConfigDir string + OSBuildWorkerS3CredsDir string + WorkerS3CredsSecretName string } // OSBuildEnvConfigReconciler reconciles a OSBuildEnvConfig object @@ -120,16 +262,20 @@ type OSBuildEnvConfigReconciler struct { CertificateRepository certificate.Repository ConfigMapRepository configmap.Repository DeploymentRepository deployment.Repository + JobRepository job.Repository ServiceRepository service.Repository SecretRepository secret.Repository + VirtualmachineRepository virtualmachine.Repository } //+kubebuilder:rbac:groups=osbuilder.project-flotta.io,resources=osbuildenvconfigs,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=osbuilder.project-flotta.io,resources=osbuildenvconfigs/status,verbs=get;update;patch //+kubebuilder:rbac:groups=osbuilder.project-flotta.io,resources=osbuildenvconfigs/finalizers,verbs=update //+kubebuilder:rbac:groups=cert-manager.io,resources=certificates,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=kubevirt.io,resources=virtualmachines,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete @@ -190,7 +336,25 @@ func (r *OSBuildEnvConfigReconciler) Update(ctx context.Context, reqLogger logr. return ctrl.Result{Requeue: true}, nil } - created, err = r.ensureCertificateExists( + created, err = r.ensureComposerExists(ctx, reqLogger, instance) + if err != nil { + return ctrl.Result{Requeue: true}, err + } else if created { + return ctrl.Result{Requeue: true}, nil + } + + created, err = r.ensureWorkersExists(ctx, reqLogger, instance) + if err != nil { + return ctrl.Result{Requeue: true}, err + } else if created { + return ctrl.Result{Requeue: true}, nil + } + + return ctrl.Result{}, nil +} + +func (r *OSBuildEnvConfigReconciler) ensureComposerExists(ctx context.Context, reqLogger logr.Logger, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + created, err := r.ensureCertificateExists( ctx, reqLogger, instance, @@ -201,19 +365,19 @@ func (r *OSBuildEnvConfigReconciler) Update(ctx context.Context, reqLogger logr. }, ) if err != nil { - return ctrl.Result{Requeue: true}, err + return false, err } else if created { reqLogger.Info("Created composer certificate") - return ctrl.Result{Requeue: true}, nil + return true, nil } composerDeploymentParams := composerDeploymentParameters{ ComposerDeploymentNamespace: conf.GlobalConf.WorkingNamespace, ComposerDeploymentName: composerDeploymentName, - ComposerImageName: composerImageName, - ComposerImageTag: composerImageTag, - ProxyImageName: envoyProxyImageName, - ProxyImageTag: envoyProxyImageTag, + ComposerImageName: conf.GlobalConf.ComposerImageName, + ComposerImageTag: conf.GlobalConf.ComposerImageTag, + ProxyImageName: conf.GlobalConf.EnvoyProxyImageName, + ProxyImageTag: conf.GlobalConf.EnvoyProxyImageTag, ComposerAPIInternalPort: composerAPIInternalPort, ComposerAPIExternalPort: composerAPIExternalPort, WorkerAPIInternalPort: workerAPIInternalPort, @@ -227,6 +391,7 @@ func (r *OSBuildEnvConfigReconciler) Update(ctx context.Context, reqLogger logr. ComposerCertsSecretPrivateKeyKey: certificateSecretKeyKey, ComposerCertsSecretCACertKey: certificateSecretCACrtKey, ProxyConfigMapName: composerProxyConfigMapName, + ProxyWorkerAPIUpstreamTimeout: (composerWorkerRequestJobTimeout * 2).String(), } if instance.Spec.Composer != nil && instance.Spec.Composer.PSQL != nil { @@ -235,50 +400,162 @@ func (r *OSBuildEnvConfigReconciler) Update(ctx context.Context, reqLogger logr. composerDeploymentParams.PgSSLMode = string(*instance.Spec.Composer.PSQL.SSLMode) } } else { - return ctrl.Result{Requeue: true}, fmt.Errorf("creating a PSQL service is not yet implemented") + return false, fmt.Errorf("creating a PSQL service is not yet implemented") } created, err = r.ensureComposerConfigMapExists(ctx, instance) if err != nil { - return ctrl.Result{Requeue: true}, err + return false, err } else if created { reqLogger.Info("Generated Composer configuration configMap") - return ctrl.Result{Requeue: true}, nil + return true, nil } created, err = r.ensureComposerProxyConfigMapExists(ctx, instance, &composerDeploymentParams) if err != nil { - return ctrl.Result{Requeue: true}, err + return false, err } else if created { reqLogger.Info("Generated Composer Proxy configuration configMap") - return ctrl.Result{Requeue: true}, nil + return true, nil } created, err = r.ensureComposerDeploymentExists(ctx, instance, &composerDeploymentParams) if err != nil { - return ctrl.Result{Requeue: true}, err + return false, err } else if created { reqLogger.Info("Generated Composer Deployment") - return ctrl.Result{Requeue: true}, nil + return true, nil } created, err = r.ensureComposerComposerAPIServiceExists(ctx, instance, &composerDeploymentParams) if err != nil { - return ctrl.Result{Requeue: true}, err + return false, err } else if created { reqLogger.Info("Generated Service for the Composer's Composer API") - return ctrl.Result{Requeue: true}, nil + return true, nil } created, err = r.ensureComposerWorkerAPIServiceExists(ctx, instance, &composerDeploymentParams) if err != nil { - return ctrl.Result{Requeue: true}, err + return false, err } else if created { reqLogger.Info("Generated Service for the Composer's Worker API") - return ctrl.Result{Requeue: true}, nil + return true, nil } - return ctrl.Result{}, nil + return false, nil +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkersExists(ctx context.Context, reqLogger logr.Logger, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + created, err := r.ensureWorkerConfigAnsibleConfigExists(ctx, instance) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated ConfigMap for Ansible Config") + return true, nil + } + + created, err = r.ensureWorkerConfigPlaybookExists(ctx, instance) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated ConfigMap for Ansible Playbook") + return true, nil + } + + created, err = r.ensureOSBuildWorkerConfigExists(ctx, instance) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated ConfigMap for Worker configuration") + return true, nil + } + + for i := range instance.Spec.Workers { + created, err = r.ensureWorkerExists(ctx, reqLogger, instance, &instance.Spec.Workers[i]) + if err != nil { + return false, err + } else if created { + return true, nil + } + } + + return false, nil +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerExists(ctx context.Context, reqLogger logr.Logger, instance *osbuildv1alpha1.OSBuildEnvConfig, worker *osbuildv1alpha1.WorkerConfig) (bool, error) { + var workerAddress string + var workerUser string + var workerSSHKeySecretName string + + if worker.VMWorkerConfig != nil { + created, err := r.ensureWorkerSSHKeysSecretExists(ctx, instance) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated Secret for SSH Keys") + return true, nil + } + + vmParameters := workerVMParameters{ + Namespace: conf.GlobalConf.WorkingNamespace, + Name: worker.Name, + ImageURL: worker.VMWorkerConfig.ImageURL, + Hostname: worker.Name, + Username: workerVMUsername, + SSHKeysSecretName: workerSSHKeysSecretName, + } + + created, err = r.ensureWorkerVMExists(ctx, &vmParameters, instance) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated VM for Worker", "name", worker.Name) + return true, nil + } + + created, err = r.ensureWorkerVMSSHServiceExists(ctx, worker.Name, instance) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated SSH Service for Worker", "name", worker.Name) + return true, nil + } + + workerAddress = fmt.Sprintf(workerSSHServiceNameFormat, worker.Name) + workerUser = workerVMUsername + workerSSHKeySecretName = workerSSHKeysSecretName + } else { + workerAddress = worker.ExternalWorkerConfig.Address + workerUser = worker.ExternalWorkerConfig.User + workerSSHKeySecretName = worker.ExternalWorkerConfig.SSHKeySecretReference.Name + } + + created, err := r.ensureWorkerCertificateExists(ctx, reqLogger, instance, worker.Name) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated Certificate for Worker", "name", worker.Name) + return true, nil + } + + created, err = r.ensureWorkerConfigInventoryExists(ctx, instance, worker.Name, workerAddress, workerUser) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated ConfigMap for Inventory file for Worker", "name", worker.Name) + return true, nil + } + + created, err = r.ensureWorkerSetupJobExists(ctx, instance, worker.Name, workerSSHKeySecretName) + if err != nil { + return false, err + } else if created { + reqLogger.Info("Generated Setup Job for Worker", "name", worker.Name) + return true, nil + } + + return false, nil } func (r *OSBuildEnvConfigReconciler) ensureCertificateExists(ctx context.Context, reqLogger logr.Logger, instance *osbuildv1alpha1.OSBuildEnvConfig, certificateName string, dnsNames []string) (bool, error) { @@ -332,26 +609,13 @@ func (r *OSBuildEnvConfigReconciler) generateCertificate(ctx context.Context, in } func (r *OSBuildEnvConfigReconciler) ensureComposerConfigMapExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { - composerConfigParams := struct { - Koji struct { - LogLevel string - } - Worker struct { - LogLevel string - RequestJobTimeout string - BasePath string - } - }{ - Koji: struct{ LogLevel string }{ + composerConfigParams := composerConfigParameters{ + Koji: composerConfigParametersKoji{ LogLevel: "info", }, - Worker: struct { - LogLevel string - RequestJobTimeout string - BasePath string - }{ + Worker: composerConfigParametersWorker{ LogLevel: "info", - RequestJobTimeout: "20s", + RequestJobTimeout: composerWorkerRequestJobTimeout.String(), BasePath: "/api/worker/v1", }, } @@ -457,13 +721,17 @@ func (r *OSBuildEnvConfigReconciler) ensureComposerWorkerAPIServiceExists(ctx co } func (r *OSBuildEnvConfigReconciler) ensureComposerServiceExists(ctx context.Context, serviceName, portName string, targetPort int, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + return r.ensureServiceExists(ctx, serviceName, portName, 443, targetPort, map[string]string{"app": "osbuild-composer"}, instance) +} + +func (r *OSBuildEnvConfigReconciler) ensureServiceExists(ctx context.Context, serviceName, portName string, port, targetPort int, selector map[string]string, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { _, err := r.ServiceRepository.Read(ctx, serviceName, conf.GlobalConf.WorkingNamespace) if err == nil { return false, nil } if errors.IsNotFound(err) { - service, err := r.generateComposerService(serviceName, portName, targetPort, instance) + service, err := r.generateService(serviceName, portName, port, targetPort, selector, instance) if err != nil { return false, err } @@ -479,7 +747,7 @@ func (r *OSBuildEnvConfigReconciler) ensureComposerServiceExists(ctx context.Con return false, err } -func (r *OSBuildEnvConfigReconciler) generateComposerService(serviceName, portName string, targetPort int, instance *osbuildv1alpha1.OSBuildEnvConfig) (*corev1.Service, error) { +func (r *OSBuildEnvConfigReconciler) generateService(serviceName, portName string, port, targetPort int, selector map[string]string, instance *osbuildv1alpha1.OSBuildEnvConfig) (*corev1.Service, error) { service := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: serviceName, @@ -490,20 +758,266 @@ func (r *OSBuildEnvConfigReconciler) generateComposerService(serviceName, portNa Ports: []corev1.ServicePort{ { Name: portName, - Port: 443, + Port: int32(port), Protocol: "TCP", TargetPort: intstr.FromInt(targetPort), }, }, - Selector: map[string]string{ - "app": "osbuild-composer", - }, + Selector: selector, }, } return service, controllerutil.SetControllerReference(instance, service, r.Scheme) } +func (r *OSBuildEnvConfigReconciler) ensureWorkerSSHKeysSecretExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + _, err := r.SecretRepository.Read(ctx, workerSSHKeysSecretName, conf.GlobalConf.WorkingNamespace) + if err == nil { + return false, nil + } + + if errors.IsNotFound(err) { + privateKeyBytes, publicKeyBytes, err := sshkey.GenerateSSHKeyPair() + if err != nil { + return false, err + } + workerSSLSecret, err := r.generateWorkerSSHKeysSecret(instance, privateKeyBytes, publicKeyBytes) + if err != nil { + return false, err + } + + err = r.SecretRepository.Create(ctx, workerSSLSecret) + if err != nil { + return false, err + } + + return true, nil + } + + return false, err +} + +func (r *OSBuildEnvConfigReconciler) generateWorkerSSHKeysSecret(instance *osbuildv1alpha1.OSBuildEnvConfig, privateKeyBytes, publicKeyBytes []byte) (*corev1.Secret, error) { + immutable := true + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: workerSSHKeysSecretName, + Namespace: conf.GlobalConf.WorkingNamespace, + }, + Immutable: &immutable, + StringData: map[string]string{ + workerSSHKeysPrivateKeyKey: string(privateKeyBytes), + workerSSHKeysPublicKeyKey: string(publicKeyBytes), + }, + } + + return secret, controllerutil.SetControllerReference(instance, secret, r.Scheme) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerVMExists(ctx context.Context, vmParameters *workerVMParameters, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + _, err := r.VirtualmachineRepository.Read(ctx, vmParameters.Name, conf.GlobalConf.WorkingNamespace) + if err == nil { + return false, nil + } + + if errors.IsNotFound(err) { + workerVm, err := r.generateWorkerVM(vmParameters, instance) + if err != nil { + return false, err + } + + err = r.VirtualmachineRepository.Create(ctx, workerVm) + if err != nil { + return false, err + } + + return true, nil + } + + return false, err +} + +func (r *OSBuildEnvConfigReconciler) generateWorkerVM(vmParameters *workerVMParameters, instance *osbuildv1alpha1.OSBuildEnvConfig) (*kubevirtv1.VirtualMachine, error) { + buf, err := templates.LoadFromTemplateFile(workerVMTemplateFile, vmParameters) + if err != nil { + return nil, err + } + + obj, groupVersionKind, err := serializer.NewCodecFactory(r.Scheme).UniversalDeserializer().Decode(buf.Bytes(), nil, nil) + if err != nil { + return nil, err + } + if *groupVersionKind != kubevirtv1.VirtualMachineGroupVersionKind { + return nil, fmt.Errorf("failed to deserializer into a VirtualMachine CR") + } + + vm, ok := obj.(*kubevirtv1.VirtualMachine) + if !ok { + return nil, fmt.Errorf("failed to cast into a VirtualMachine object") + } + + return vm, controllerutil.SetControllerReference(instance, vm, r.Scheme) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerVMSSHServiceExists(ctx context.Context, workerName string, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + return r.ensureServiceExists(ctx, fmt.Sprintf(workerSSHServiceNameFormat, workerName), workerSSHPortName, 22, 22, map[string]string{"osbuild-worker": workerName}, instance) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerCertificateExists(ctx context.Context, reqLogger logr.Logger, instance *osbuildv1alpha1.OSBuildEnvConfig, workerName string) (bool, error) { + return r.ensureCertificateExists(ctx, reqLogger, instance, fmt.Sprintf(workerCertificateNameFormat, workerName), []string{workerName}) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerConfigPlaybookExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + workerSetupPlaybookParams := workerSetupPlaybookParameters{ + RPMRepoDistribution: workerRPMRepoDistribution, + OSBuildComposerTag: conf.GlobalConf.WorkerOSBuildComposerVersion, + OSBuildTag: conf.GlobalConf.WorkerOSBuildVersion, + RHCredentialsDir: workerRHCredentialsDir, + RHCredentialsUsernameKey: workerRHCredentialsUsernameKey, + RHCredentialsPasswordKey: workerRHCredentialsPasswordKey, + OSBuildWorkerCertsDir: workerOSBuildWorkerCertsDir, + ComposerWorkerAPIServiceName: composerWorkerAPIServiceName, + OSBuildWorkerConfigDir: workerOSBuildWorkerConfigDir, + OSBuildWorkerConfigFile: workerOSBuildWorkerConfigConfigMapKey, + OSBuildWorkerS3CredsFile: workerOSBuildWorkerConfigS3CredentialsFile, + OSBuildWorkerS3CredsDir: workerOSBuildWorkerS3CredsDir, + OSBuildWorkerS3CredsAccessKeyIDKey: workerOSBuildWorkerS3CredsAccessKeyIDKey, + OSBuildWorkerS3CredsSecretAccessKeyKey: workerOSBuildWorkerS3CredsSecretAccessKeyKey, + OSBuildWorkerS3CABundleFile: workerOSBuildWorkerConfigS3CABundleFile, + OSBuildWorkerS3CABundleDir: workerOSBuildWorkerS3CABundleDir, + OSBuildWorkerS3CABundleKey: workerOSBuildWorkerS3CABundleKey, + } + return r.ensureConfigMapForTemplateFileExists(ctx, workerSetupPlaybookConfigMapName, workerSetupPlaybookConfigMapKey, workerSetupPlaybookTemplateFile, workerSetupPlaybookParams, instance) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerConfigAnsibleConfigExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + return r.ensureConfigMapForTemplateFileExists(ctx, workerSetupAnsibleConfigConfigMapName, workerSetupAnsibleConfigConfigMapKey, workerSetupAnsibleConfigTemplateFile, nil, instance) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerConfigInventoryExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig, workerName, workerAddress, workerUser string) (bool, error) { + workerSetupInventoryParams := workerSetupInventoryParameters{ + Address: workerAddress, + User: workerUser, + SSHKey: path.Join(workerSetupJobSSHKeyDir, workerSSHKeysPrivateKeyKey), + } + return r.ensureConfigMapForTemplateFileExists(ctx, fmt.Sprintf(workerSetupInventoryConfigMapNameFormat, workerName), workerSetupInventoryConfigMapKey, workerSetupInventoryTemplateFile, workerSetupInventoryParams, instance) +} + +func (r *OSBuildEnvConfigReconciler) ensureOSBuildWorkerConfigExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig) (bool, error) { + workerOSBuildWorkerConfigParams := workerOSBuildWorkerConfigParameters{ + CredentialsFile: workerOSBuildWorkerConfigS3CredentialsFile, + } + + if instance.Spec.S3Service.AWS != nil { + workerOSBuildWorkerConfigParams.Bucket = instance.Spec.S3Service.AWS.Bucket + } else { + workerOSBuildWorkerConfigParams.Bucket = instance.Spec.S3Service.GenericS3.Bucket + workerOSBuildWorkerConfigParams.GenericS3 = &workerOSBuildWorkerConfigParametersGenericS3{ + Region: instance.Spec.S3Service.GenericS3.Region, + Endpoint: instance.Spec.S3Service.GenericS3.Endpoint, + } + if instance.Spec.S3Service.GenericS3.CABundleSecretReference != nil { + caBundleFile := workerOSBuildWorkerConfigS3CABundleFile + workerOSBuildWorkerConfigParams.GenericS3.CABundleFile = &caBundleFile + } + if instance.Spec.S3Service.GenericS3.SkipSSLVerification != nil { + workerOSBuildWorkerConfigParams.GenericS3.SkipSSLVerification = instance.Spec.S3Service.GenericS3.SkipSSLVerification + } + } + return r.ensureConfigMapForTemplateFileExists(ctx, workerOSBuildWorkerConfigConfigMapName, workerOSBuildWorkerConfigConfigMapKey, workerOSBuildWorkerConfigTemplateFile, workerOSBuildWorkerConfigParams, instance) +} + +func (r *OSBuildEnvConfigReconciler) ensureWorkerSetupJobExists(ctx context.Context, instance *osbuildv1alpha1.OSBuildEnvConfig, workerName, workerSSHKeySecretName string) (bool, error) { + _, err := r.JobRepository.Read(ctx, fmt.Sprintf(workerSetupJobNameFormat, workerName), conf.GlobalConf.WorkingNamespace) + if err == nil { + return false, nil + } + + if errors.IsNotFound(err) { + workerSetupJob, err := r.generateWorkerSetupJob(workerName, workerSSHKeySecretName, instance) + if err != nil { + return false, err + } + + err = r.JobRepository.Create(ctx, workerSetupJob) + if err != nil { + return false, err + } + + return true, nil + } + + return false, err +} + +func (r *OSBuildEnvConfigReconciler) generateWorkerSetupJob(workerName, workerSSHKeySecretName string, instance *osbuildv1alpha1.OSBuildEnvConfig) (*batchv1.Job, error) { + workerSetupJobParams := workerSetupJobParameters{ + WorkerConfigJobNamespace: conf.GlobalConf.WorkingNamespace, + WorkerConfigJobName: fmt.Sprintf(workerSetupJobNameFormat, workerName), + WorkerConfigJobImageName: conf.GlobalConf.WorkerSetupImageName, + WorkerConfigJobImageTag: conf.GlobalConf.WorkerSetupImageTag, + WorkerConfigAnsibleConfigConfigMapKey: workerSetupAnsibleConfigConfigMapKey, + WorkerConfigInventoryConfigMapKey: workerSetupInventoryConfigMapKey, + WorkerConfigPlaybookConfigMapKey: workerSetupPlaybookConfigMapKey, + WorkerConfigJobSSHKeyDir: workerSetupJobSSHKeyDir, + RHCredentialsDir: workerRHCredentialsDir, + OSBuildWorkerCertsDir: workerOSBuildWorkerCertsDir, + WorkerSSHKeysSecretName: workerSSHKeySecretName, + WorkerConfigAnsibleConfigConfigMapName: workerSetupAnsibleConfigConfigMapName, + WorkerConfigPlaybookConfigMapName: workerSetupPlaybookConfigMapName, + WorkerConfigInventoryConfigMapName: fmt.Sprintf(workerSetupInventoryConfigMapNameFormat, workerName), + RedHatCredsSecretName: instance.Spec.RedHatCredsSecretReference.Name, + WorkerCertificateName: fmt.Sprintf(workerCertificateNameFormat, workerName), + WorkerOSBuildWorkerConfigConfigMapName: workerOSBuildWorkerConfigConfigMapName, + OSBuildWorkerConfigDir: workerOSBuildWorkerConfigDir, + OSBuildWorkerS3CredsDir: workerOSBuildWorkerS3CredsDir, + } + + if instance.Spec.S3Service.AWS != nil { + workerSetupJobParams.WorkerS3CredsSecretName = instance.Spec.S3Service.AWS.CredsSecretReference.Name + } else { + workerSetupJobParams.WorkerS3CredsSecretName = instance.Spec.S3Service.GenericS3.CredsSecretReference.Name + } + + buf, err := templates.LoadFromTemplateFile(workerSetupJobTemplateFile, workerSetupJobParams) + if err != nil { + return nil, err + } + + decode := scheme.Codecs.UniversalDeserializer().Decode + obj, _, err := decode(buf.Bytes(), nil, nil) + if err != nil { + return nil, err + + } + + job, ok := obj.(*batchv1.Job) + if !ok { + return nil, fmt.Errorf("failed to deserialize the job object") + } + + if instance.Spec.S3Service.GenericS3 != nil && instance.Spec.S3Service.GenericS3.CABundleSecretReference != nil { + caBundleSecretVolumeName := "s3-ca-bundle" // #nosec G101 + caBundleSecretVolume := corev1.Volume{ + Name: caBundleSecretVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: instance.Spec.S3Service.GenericS3.CABundleSecretReference.Name, + }, + }, + } + job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, caBundleSecretVolume) + + caBundleVolumeMount := corev1.VolumeMount{ + Name: caBundleSecretVolumeName, + MountPath: workerOSBuildWorkerS3CABundleDir, + } + job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, caBundleVolumeMount) + } + + return job, controllerutil.SetControllerReference(instance, job, r.Scheme) +} + func (r *OSBuildEnvConfigReconciler) Finalize(ctx context.Context, reqLogger logr.Logger, instance *osbuildv1alpha1.OSBuildEnvConfig) (ctrl.Result, error) { // By default, cert-manager does not delete the secret is creates when the certificate is deleted so need to delete it manually deleted, err := r.ensureComposerCertSecretDeleted(ctx) @@ -515,6 +1029,17 @@ func (r *OSBuildEnvConfigReconciler) Finalize(ctx context.Context, reqLogger log return ctrl.Result{Requeue: true}, nil } + for _, worker := range instance.Spec.Workers { + deleted, err = r.ensureWorkerCertSecretDeleted(ctx, worker.Name) + if err != nil { + return ctrl.Result{Requeue: true}, err + } + if deleted { + reqLogger.Info("Deleted certificate secret for", "worker", worker.Name) + return ctrl.Result{Requeue: true}, nil + } + } + err = r.removeFinalizer(ctx, reqLogger, instance) if err != nil { return ctrl.Result{Requeue: true}, err @@ -535,6 +1060,10 @@ func (r *OSBuildEnvConfigReconciler) ensureComposerCertSecretDeleted(ctx context return r.ensureSecretDeleted(ctx, composerCertificateName) } +func (r *OSBuildEnvConfigReconciler) ensureWorkerCertSecretDeleted(ctx context.Context, workerName string) (bool, error) { + return r.ensureSecretDeleted(ctx, fmt.Sprintf(workerCertificateNameFormat, workerName)) +} + func (r *OSBuildEnvConfigReconciler) ensureSecretDeleted(ctx context.Context, secretName string) (bool, error) { secret, err := r.SecretRepository.Read(ctx, secretName, conf.GlobalConf.WorkingNamespace) if err != nil { diff --git a/controllers/osbuildenvconfig_controller_test.go b/controllers/osbuildenvconfig_controller_test.go index 8aa922b8..529c89ff 100644 --- a/controllers/osbuildenvconfig_controller_test.go +++ b/controllers/osbuildenvconfig_controller_test.go @@ -47,6 +47,13 @@ var _ = Describe("OSBuildEnvConfig Controller", func() { osBuildOperatorFinalizer = "osbuilder.project-flotta.io/osBuildOperatorFinalizer" composerCertificateName = "composer-cert" templatesDir = "../resources/templates" + workerSetupImageName = "quay.io/project-flotta/osbuild-operator-worker-setup:latest" + + genericS3CredsSecretName = "genericS3CredsSecretName" // #nosec G101 + genericS3Region = "us-east-1" + genericS3Bucket = "test-bucket" + genericS3Endpoint = "https://somewhere" + genericS3CABundleSecretName = "genericS3CABundleSecretName" // #nosec G101 ) var ( @@ -90,6 +97,7 @@ var _ = Describe("OSBuildEnvConfig Controller", func() { os.Setenv("WORKING_NAMESPACE", operatorNamespace) os.Setenv("CA_ISSUER_NAME", caIssuerName) os.Setenv("TEMPLATES_DIR", templatesDir) + os.Setenv("WORKER_SETUP_IMAGE", workerSetupImageName) err := conf.Load() Expect(err).To(BeNil()) @@ -135,6 +143,22 @@ var _ = Describe("OSBuildEnvConfig Controller", func() { }, Spec: osbuildv1alpha1.OSBuildEnvConfigSpec{ Composer: &osbuildv1alpha1.ComposerConfig{}, + S3Service: osbuildv1alpha1.S3ServiceConfig{ + GenericS3: &osbuildv1alpha1.GenericS3ServiceConfig{ + AWSS3ServiceConfig: &osbuildv1alpha1.AWSS3ServiceConfig{ + CredsSecretReference: buildv1.SecretLocalReference{ + Name: genericS3CredsSecretName, + }, + Region: genericS3Region, + Bucket: genericS3Bucket, + }, + Endpoint: genericS3Endpoint, + CABundleSecretReference: &buildv1.SecretLocalReference{ + Name: genericS3CABundleSecretName, + }, + SkipSSLVerification: pointer.Bool(true), + }, + }, }, } }) @@ -716,17 +740,182 @@ var _ = Describe("OSBuildEnvConfig Controller", func() { }) }) - Context("Composer API Service exists", func() { + Context("Worker API Service exists", func() { + const ( + workerConfigAnsibleConfigConfigMapName = "osbuild-worker-setup-ansible-config" + ) + BeforeEach(func() { serviceRepository.EXPECT().Read(requestContext, composerWorkerAPIServiceName, operatorNamespace).Return(&composerWorkerAPIService, nil) }) - It("Should return Done", func() { + It("Should return an error if failed to get the configMap for the ansible config ", func() { + // given + configMapRepository.EXPECT().Read(requestContext, workerConfigAnsibleConfigConfigMapName, operatorNamespace).Return(nil, errFailed) // when result, err := reconciler.Reconcile(requestContext, request) // then - Expect(err).To(BeNil()) - Expect(result).To(Equal(resultDone)) + Expect(err).To(Equal(errFailed)) + Expect(result).To(Equal(resultRequeue)) + }) + + Context("ConfigMap for configuration ansible config not found", func() { + BeforeEach(func() { + configMapRepository.EXPECT().Read(requestContext, workerConfigAnsibleConfigConfigMapName, operatorNamespace).Return(nil, errNotFound) + }) + + It("Should return an error if failed to create the configMap for the ansible config for the worker configuration job", func() { + // given + configMapRepository.EXPECT().Create(requestContext, gomock.Any()).Return(errFailed) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(Equal(errFailed)) + Expect(result).To(Equal(resultRequeue)) + }) + + It("Should return requeue if succeeded to create the configMap for the ansible config for the worker configuration job", func() { + // given + configMapRepository.EXPECT().Create(requestContext, gomock.Any()).Return(nil) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(BeNil()) + Expect(result).To(Equal(resultRequeue)) + }) + }) + + Context("ConfigMap for the ansible config exists", func() { + const ( + workerConfigPlaybookConfigMapName = "osbuild-worker-setup-playbook" + ) + + var ( + workerConfigAnsibleConfigConfigMap = corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: operatorNamespace, + Name: workerConfigAnsibleConfigConfigMapName, + }, + } + ) + + BeforeEach(func() { + configMapRepository.EXPECT().Read(requestContext, workerConfigAnsibleConfigConfigMapName, operatorNamespace).Return(&workerConfigAnsibleConfigConfigMap, nil) + }) + + It("Should return an error if failed to get the configMap for the ansible config ", func() { + // given + configMapRepository.EXPECT().Read(requestContext, workerConfigPlaybookConfigMapName, operatorNamespace).Return(nil, errFailed) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(Equal(errFailed)) + Expect(result).To(Equal(resultRequeue)) + }) + + Context("ConfigMap for configuration playbook not found", func() { + BeforeEach(func() { + configMapRepository.EXPECT().Read(requestContext, workerConfigPlaybookConfigMapName, operatorNamespace).Return(nil, errNotFound) + }) + + It("Should return an error if failed to create the configMap for the playbook for the worker configuration job", func() { + // given + configMapRepository.EXPECT().Create(requestContext, gomock.Any()).Return(errFailed) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(Equal(errFailed)) + Expect(result).To(Equal(resultRequeue)) + }) + + It("Should return requeue if succeeded to create the configMap for the playbook for the worker configuration job", func() { + // given + configMapRepository.EXPECT().Create(requestContext, gomock.Any()).Return(nil) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(BeNil()) + Expect(result).To(Equal(resultRequeue)) + }) + }) + + Context("ConfigMap for configuration playbook exists", func() { + const ( + workerOSBuildWorkerConfigConfigMapName = "osbuild-worker-config" + ) + + var ( + workerConfigPlaybookConfigMap = corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: operatorNamespace, + Name: workerConfigPlaybookConfigMapName, + }, + } + ) + + BeforeEach(func() { + configMapRepository.EXPECT().Read(requestContext, workerConfigPlaybookConfigMapName, operatorNamespace).Return(&workerConfigPlaybookConfigMap, nil) + }) + + It("Should return an error if failed to get the configMap for the osbuild-worker config", func() { + // given + configMapRepository.EXPECT().Read(requestContext, workerOSBuildWorkerConfigConfigMapName, operatorNamespace).Return(nil, errFailed) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(Equal(errFailed)) + Expect(result).To(Equal(resultRequeue)) + }) + + Context("ConfigMap for osbuild-worker config not found", func() { + BeforeEach(func() { + configMapRepository.EXPECT().Read(requestContext, workerOSBuildWorkerConfigConfigMapName, operatorNamespace).Return(nil, errNotFound) + }) + + It("Should return an error if failed to create the configMap for the osbuild-worker config", func() { + // given + configMapRepository.EXPECT().Create(requestContext, gomock.Any()).Return(errFailed) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(Equal(errFailed)) + Expect(result).To(Equal(resultRequeue)) + }) + + It("Should return requeue if succeeded to create the configMap for the osbuild-worker config", func() { + // given + configMapRepository.EXPECT().Create(requestContext, gomock.Any()).Return(nil) + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(BeNil()) + Expect(result).To(Equal(resultRequeue)) + }) + }) + + Context("ConfigMap for the osbuild-worker config exists", func() { + var ( + workerOSBuildWorkerConfigConfigMap = corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: operatorNamespace, + Name: workerOSBuildWorkerConfigConfigMapName, + }, + } + ) + + BeforeEach(func() { + configMapRepository.EXPECT().Read(requestContext, workerOSBuildWorkerConfigConfigMapName, operatorNamespace).Return(&workerOSBuildWorkerConfigConfigMap, nil) + }) + + It("Should return Done", func() { + // when + result, err := reconciler.Reconcile(requestContext, request) + // then + Expect(err).To(BeNil()) + Expect(result).To(Equal(resultDone)) + }) + }) + }) }) }) }) diff --git a/go.mod b/go.mod index 94396ca1..ad032f9d 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,10 @@ require ( require ( github.com/golang-jwt/jwt/v4 v4.0.0 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/openshift/custom-resource-status v1.1.2 // indirect + github.com/pborman/uuid v1.2.0 // indirect + kubevirt.io/containerized-data-importer-api v1.47.0 // indirect + kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/gateway-api v0.4.1 // indirect ) @@ -76,7 +80,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 - golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 // indirect + golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d golang.org/x/net v0.0.0-20220513224357-95641704303c // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect @@ -100,4 +104,7 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -require github.com/go-logr/logr v1.2.3 +require ( + github.com/go-logr/logr v1.2.3 + kubevirt.io/api v0.54.0 +) diff --git a/go.sum b/go.sum index 3a39d2a4..7d88a42d 100644 --- a/go.sum +++ b/go.sum @@ -476,6 +476,7 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= @@ -1043,6 +1044,8 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3 github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/openshift/api v3.9.0+incompatible h1:fJ/KsefYuZAjmrr3+5U9yZIZbTOpVkDDLDLFresAeYs= github.com/openshift/api v3.9.0+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY= +github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= +github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/orangecms/go-framebuffer v0.0.0-20200613202404-a0700d90c330/go.mod h1:3Myb/UszJY32F2G7yGkUtcW/ejHpjlGfYLim7cv2uKA= @@ -1052,6 +1055,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pavel-v-chernykh/keystore-go/v4 v4.1.0/go.mod h1:2ejgys4qY+iNVW1IittZhyRYA6MNv8TgM6VHqojbB9g= github.com/pavel-v-chernykh/keystore-go/v4 v4.2.0/go.mod h1:VxOBKEAW8/EJjil9qwfvVDSljDW0DCoZMD4ezsq9n8U= github.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= @@ -1369,8 +1373,9 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 h1:NUzdAbFtCJSXU20AOXgeqaUwg8Ypg4MPYmL+d+rsB5c= golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1408,6 +1413,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1757,6 +1763,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1994,13 +2001,17 @@ k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= k8s.io/api v0.23.0/go.mod h1:8wmDdLBHBNxtOIytwLstXt5E9PddnZb0GaMcqsvDBpg= +k8s.io/api v0.23.1/go.mod h1:WfXnOnwSqNtG62Y1CdjoMxh7r7u9QXGCkA1u0na2jgo= +k8s.io/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ= k8s.io/api v0.23.4/go.mod h1:i77F4JfyNNrhOjZF7OwwNJS5Y1S9dpwvb9iYRYRczfI= +k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI= k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo= k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= k8s.io/apiextensions-apiserver v0.23.0/go.mod h1:xIFAEEDlAZgpVBl/1VSjGDmLoXAWRG40+GsWhKhAxY4= +k8s.io/apiextensions-apiserver v0.23.1/go.mod h1:0qz4fPaHHsVhRApbtk3MGXNn2Q9M/cVWWhfHdY2SxiM= k8s.io/apiextensions-apiserver v0.23.4/go.mod h1:TWYAKymJx7nLMxWCgWm2RYGXHrGlVZnxIlGnvtfYu+g= k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k= k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ= @@ -2012,7 +2023,10 @@ k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCF k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apimachinery v0.23.0/go.mod h1:fFCTTBKvKcwTPFzjlcxp91uPFZr+JA0FubU4fLzzFYc= +k8s.io/apimachinery v0.23.1/go.mod h1:SADt2Kl8/sttJ62RRsi9MIV4o8f5S3coArm0Iu3fBno= +k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= k8s.io/apimachinery v0.23.4/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= +k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM= k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw= @@ -2022,6 +2036,7 @@ k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= k8s.io/apiserver v0.23.0/go.mod h1:Cec35u/9zAepDPPFyT+UMrgqOCjgJ5qtfVJDxjZYmt4= +k8s.io/apiserver v0.23.1/go.mod h1:Bqt0gWbeM2NefS8CjWswwd2VNAKN6lUKR85Ft4gippY= k8s.io/apiserver v0.23.4/go.mod h1:A6l/ZcNtxGfPSqbFDoxxOjEjSKBaQmE+UTveOmMkpNc= k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI= k8s.io/cli-runtime v0.23.4/go.mod h1:7KywUNTUibmHPqmpDFuRO1kc9RhsufHv2lkjCm2YZyM= @@ -2033,6 +2048,7 @@ k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= k8s.io/client-go v0.23.0/go.mod h1:hrDnpnK1mSr65lHHcUuIZIXDgEbzc7/683c6hyG4jTA= +k8s.io/client-go v0.23.1/go.mod h1:6QSI8fEuqD4zgFK0xbdwfB/PthBsIxCJMa3s17WlcO0= k8s.io/client-go v0.23.4/go.mod h1:PKnIL4pqLuvYUK1WU7RLTMYKPiIh7MYShLshtRY9cj0= k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA= k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= @@ -2042,6 +2058,8 @@ k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6g k8s.io/code-generator v0.22.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/code-generator v0.23.0/go.mod h1:vQvOhDXhuzqiVfM/YHp+dmg10WDZCchJVObc9MvowsE= +k8s.io/code-generator v0.23.1/go.mod h1:V7yn6VNTCWW8GqodYCESVo95fuiEg713S8B7WacWZDA= +k8s.io/code-generator v0.23.3/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk= k8s.io/code-generator v0.23.4/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk= k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c= @@ -2051,6 +2069,7 @@ k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMY k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= k8s.io/component-base v0.23.0/go.mod h1:DHH5uiFvLC1edCpvcTDV++NKULdYYU6pR9Tt3HIKMKI= +k8s.io/component-base v0.23.1/go.mod h1:6llmap8QtJIXGDd4uIWJhAq0Op8AtQo6bDW2RrNMTeo= k8s.io/component-base v0.23.4/go.mod h1:8o3Gg8i2vnUXGPOwciiYlkSaZT+p+7gA9Scoz8y4W4E= k8s.io/component-base v0.24.2 h1:kwpQdoSfbcH+8MPN4tALtajLDfSfYxBDYlXobNWI6OU= k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM= @@ -2080,6 +2099,7 @@ k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-aggregator v0.23.4/go.mod h1:hpmPi4oaLBe014CkBCqzBYWok64H2C7Ka6FBLJvHgkg= @@ -2089,6 +2109,7 @@ k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAG k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= +k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kubectl v0.23.4/go.mod h1:Dgb0Rvx/8JKS/C2EuvsNiQc6RZnX0SbHJVG3XUzH6ok= @@ -2105,6 +2126,12 @@ k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +kubevirt.io/api v0.54.0 h1:rVHaKrsxpYf5Cu6rhASOxNTChS76Nvtn5tArtG2M2Ds= +kubevirt.io/api v0.54.0/go.mod h1:mK8ilpVLcZraqgo7hv2OSNQ5vdsA3G9Pxn8LY2/1+IY= +kubevirt.io/containerized-data-importer-api v1.47.0 h1:fncmQ/2J8MVb3c2snNkUXlBQX472nqCjJJ2AduuMrDc= +kubevirt.io/containerized-data-importer-api v1.47.0/go.mod h1:yjD8pGZVMCeqcN46JPUQdZ2JwRVoRCOXrTVyNuFvrLo= +kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= +kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= oras.land/oras-go v1.1.0/go.mod h1:1A7vR/0KknT2UkJVWh+xMi95I/AhK8ZrxrnUSmXN0bQ= pack.ag/tftp v1.0.1-0.20181129014014-07909dfbde3c/go.mod h1:N1Pyo5YG+K90XHoR2vfLPhpRuE8ziqbgMn/r/SghZas= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/internal/conf/config.go b/internal/conf/config.go index 23fac8e2..f888d743 100644 --- a/internal/conf/config.go +++ b/internal/conf/config.go @@ -34,6 +34,30 @@ type OperatorConfig struct { // TemplatesDir is the path to the directory where the templates are stored TemplatesDir string `envconfig:"TEMPLATES_DIR" default:"/templates"` + + // WorkerSetupImageName is the name of the image to use for the Worker Setup job + WorkerSetupImageName string `envconfig:"WORKER_SETUP_IMAGE_NAME" default:"quay.io/project-flotta/osbuild-operator-worker-setup"` + + // WorkerSetupImageTag is the tag of the image to use for the Worker Setup job + WorkerSetupImageTag string `envconfig:"WORKER_SETUP_IMAGE_TAG" default:"v0.1"` + + // ComposerImageName is the name of the image to use for the Composer API + ComposerImageName string `envconfig:"COMPOSER_IMAGE_NAME" default:"quay.io/app-sre/composer"` + + // ComposerImageTag is the tag of the image to use for the Composer API + ComposerImageTag string `envconfig:"COMPOSER_IMAGE_TAG" default:"37fc807"` + + // EnvoyProxyImageName is the name of the image to use for the Composer's Proxy server + EnvoyProxyImageName string `envconfig:"ENVOY_PROXY_IMAGE_NAME" default:"docker.io/envoyproxy/envoy"` + + // EnvoyProxyImageTag is the tag of the image to use for the Composer API + EnvoyProxyImageTag string `envconfig:"ENVOY_PROXY_IMAGE_TAG" default:"v1.21-latest"` + + // WorkerOSBuildComposerVersion is the release tag of OSBuild-Composer for the osbuild-worker RPM + WorkerOSBuildComposerVersion string `envconfig:"WORKER_OSBUILD_COMPOSER_VERSION" default:"v56"` + + // WorkerOSBuildVersion is the release tag of OSBuild for the osbuild RPM + WorkerOSBuildVersion string `envconfig:"WORKER_OSBUILD_VERSION" default:"v59"` } var GlobalConf *OperatorConfig diff --git a/internal/repository/job/job.go b/internal/repository/job/job.go new file mode 100644 index 00000000..d28ae1a0 --- /dev/null +++ b/internal/repository/job/job.go @@ -0,0 +1,34 @@ +package job + +import ( + "context" + + _ "github.com/golang/mock/mockgen/model" + + batchv1 "k8s.io/api/batch/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +//go:generate mockgen -package=job -destination=mock_job.go . Repository +type Repository interface { + Read(ctx context.Context, name string, namespace string) (*batchv1.Job, error) + Create(ctx context.Context, job *batchv1.Job) error +} + +type CRRepository struct { + client client.Client +} + +func NewJobRepository(client client.Client) *CRRepository { + return &CRRepository{client: client} +} + +func (r *CRRepository) Read(ctx context.Context, name string, namespace string) (*batchv1.Job, error) { + job := batchv1.Job{} + err := r.client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &job) + return &job, err +} + +func (r *CRRepository) Create(ctx context.Context, job *batchv1.Job) error { + return r.client.Create(ctx, job) +} diff --git a/internal/repository/job/mock_job.go b/internal/repository/job/mock_job.go new file mode 100644 index 00000000..a8cf70a4 --- /dev/null +++ b/internal/repository/job/mock_job.go @@ -0,0 +1,65 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/project-flotta/osbuild-operator/internal/repository/job (interfaces: Repository) + +// Package job is a generated GoMock package. +package job + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "k8s.io/api/batch/v1" +) + +// MockRepository is a mock of Repository interface. +type MockRepository struct { + ctrl *gomock.Controller + recorder *MockRepositoryMockRecorder +} + +// MockRepositoryMockRecorder is the mock recorder for MockRepository. +type MockRepositoryMockRecorder struct { + mock *MockRepository +} + +// NewMockRepository creates a new mock instance. +func NewMockRepository(ctrl *gomock.Controller) *MockRepository { + mock := &MockRepository{ctrl: ctrl} + mock.recorder = &MockRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockRepository) EXPECT() *MockRepositoryMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockRepository) Create(arg0 context.Context, arg1 *v1.Job) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create. +func (mr *MockRepositoryMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockRepository)(nil).Create), arg0, arg1) +} + +// Read mocks base method. +func (m *MockRepository) Read(arg0 context.Context, arg1, arg2 string) (*v1.Job, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Read", arg0, arg1, arg2) + ret0, _ := ret[0].(*v1.Job) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Read indicates an expected call of Read. +func (mr *MockRepositoryMockRecorder) Read(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockRepository)(nil).Read), arg0, arg1, arg2) +} diff --git a/internal/repository/virtualmachine/mock_virtualmachine.go b/internal/repository/virtualmachine/mock_virtualmachine.go new file mode 100644 index 00000000..e15c3662 --- /dev/null +++ b/internal/repository/virtualmachine/mock_virtualmachine.go @@ -0,0 +1,65 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/project-flotta/osbuild-operator/internal/repository/virtualmachine (interfaces: Repository) + +// Package virtualmachine is a generated GoMock package. +package virtualmachine + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "kubevirt.io/api/core/v1" +) + +// MockRepository is a mock of Repository interface. +type MockRepository struct { + ctrl *gomock.Controller + recorder *MockRepositoryMockRecorder +} + +// MockRepositoryMockRecorder is the mock recorder for MockRepository. +type MockRepositoryMockRecorder struct { + mock *MockRepository +} + +// NewMockRepository creates a new mock instance. +func NewMockRepository(ctrl *gomock.Controller) *MockRepository { + mock := &MockRepository{ctrl: ctrl} + mock.recorder = &MockRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockRepository) EXPECT() *MockRepositoryMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockRepository) Create(arg0 context.Context, arg1 *v1.VirtualMachine) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create. +func (mr *MockRepositoryMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockRepository)(nil).Create), arg0, arg1) +} + +// Read mocks base method. +func (m *MockRepository) Read(arg0 context.Context, arg1, arg2 string) (*v1.VirtualMachine, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Read", arg0, arg1, arg2) + ret0, _ := ret[0].(*v1.VirtualMachine) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Read indicates an expected call of Read. +func (mr *MockRepositoryMockRecorder) Read(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockRepository)(nil).Read), arg0, arg1, arg2) +} diff --git a/internal/repository/virtualmachine/virtualmachine.go b/internal/repository/virtualmachine/virtualmachine.go new file mode 100644 index 00000000..227d84a8 --- /dev/null +++ b/internal/repository/virtualmachine/virtualmachine.go @@ -0,0 +1,34 @@ +package virtualmachine + +import ( + "context" + + _ "github.com/golang/mock/mockgen/model" + + kubevirtv1 "kubevirt.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +//go:generate mockgen -package=virtualmachine -destination=mock_virtualmachine.go . Repository +type Repository interface { + Read(ctx context.Context, name string, namespace string) (*kubevirtv1.VirtualMachine, error) + Create(ctx context.Context, virtualmachine *kubevirtv1.VirtualMachine) error +} + +type CRRepository struct { + client client.Client +} + +func NewVirtualMachineRepository(client client.Client) *CRRepository { + return &CRRepository{client: client} +} + +func (r *CRRepository) Read(ctx context.Context, name string, namespace string) (*kubevirtv1.VirtualMachine, error) { + virtualmachine := kubevirtv1.VirtualMachine{} + err := r.client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &virtualmachine) + return &virtualmachine, err +} + +func (r *CRRepository) Create(ctx context.Context, virtualmachine *kubevirtv1.VirtualMachine) error { + return r.client.Create(ctx, virtualmachine) +} diff --git a/internal/sshkey/sshkey.go b/internal/sshkey/sshkey.go new file mode 100644 index 00000000..96d3bf65 --- /dev/null +++ b/internal/sshkey/sshkey.go @@ -0,0 +1,71 @@ +package sshkey + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + + "golang.org/x/crypto/ssh" +) + +const ( + privateKeyBitSize = 4096 +) + +func GenerateSSHKeyPair() ([]byte, []byte, error) { + privateKey, err := generatePrivateKey(privateKeyBitSize) + if err != nil { + return nil, nil, err + } + + publicKeyBytes, err := generatePublicKey(&privateKey.PublicKey) + if err != nil { + return nil, nil, err + } + + return encodePrivateKeyToPEM(privateKey), publicKeyBytes, nil +} + +// generatePrivateKey creates a RSA Private Key of specified byte size +func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) { + // Private Key generation + privateKey, err := rsa.GenerateKey(rand.Reader, bitSize) + if err != nil { + return nil, err + } + + // Validate Private Key + err = privateKey.Validate() + if err != nil { + return nil, err + } + + return privateKey, nil +} + +// encodePrivateKeyToPEM encodes Private Key from RSA to PEM format +func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte { + // Get ASN.1 DER format + privDER := x509.MarshalPKCS1PrivateKey(privateKey) + + // pem.Block + privBlock := pem.Block{ + Type: "RSA PRIVATE KEY", + Headers: nil, + Bytes: privDER, + } + + // Private key in PEM format + return pem.EncodeToMemory(&privBlock) +} + +// generatePublicKey take a rsa.PublicKey and return bytes suitable for writing to .pub file +// returns in the format "ssh-rsa ..." +func generatePublicKey(privatekey *rsa.PublicKey) ([]byte, error) { + publicRsaKey, err := ssh.NewPublicKey(privatekey) + if err != nil { + return nil, err + } + return ssh.MarshalAuthorizedKey(publicRsaKey), nil +} diff --git a/main.go b/main.go index 49589294..2e2a4eec 100644 --- a/main.go +++ b/main.go @@ -38,6 +38,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + kubevirtv1 "kubevirt.io/api/core/v1" "github.com/project-flotta/osbuild-operator/api/v1alpha1" "github.com/project-flotta/osbuild-operator/controllers" @@ -48,12 +49,14 @@ import ( "github.com/project-flotta/osbuild-operator/internal/repository/certificate" "github.com/project-flotta/osbuild-operator/internal/repository/configmap" "github.com/project-flotta/osbuild-operator/internal/repository/deployment" + "github.com/project-flotta/osbuild-operator/internal/repository/job" "github.com/project-flotta/osbuild-operator/internal/repository/osbuild" "github.com/project-flotta/osbuild-operator/internal/repository/osbuildconfig" "github.com/project-flotta/osbuild-operator/internal/repository/osbuildconfigtemplate" "github.com/project-flotta/osbuild-operator/internal/repository/osbuildenvconfig" "github.com/project-flotta/osbuild-operator/internal/repository/secret" "github.com/project-flotta/osbuild-operator/internal/repository/service" + "github.com/project-flotta/osbuild-operator/internal/repository/virtualmachine" //+kubebuilder:scaffold:imports ) @@ -73,6 +76,8 @@ func init() { utilruntime.Must(v1alpha1.AddToScheme(scheme)) utilruntime.Must(certmanagerv1.AddToScheme(scheme)) + + utilruntime.Must(kubevirtv1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -123,8 +128,10 @@ func main() { configMapRepository := configmap.NewConfigMapRepository(mgr.GetClient()) certificateRepository := certificate.NewCertificateRepository(mgr.GetClient()) deploymentRepository := deployment.NewDeploymentRepository(mgr.GetClient()) + jobRepository := job.NewJobRepository(mgr.GetClient()) serviceRepository := service.NewServiceRepository(mgr.GetClient()) secretRepository := secret.NewSecretRepository(mgr.GetClient()) + virtualMachineRepository := virtualmachine.NewVirtualMachineRepository(mgr.GetClient()) osBuildCRCreator := manifests.NewOSBuildCRCreator(osBuildConfigRepository, osBuildRepository, scheme, osBuildConfigTemplateRepository, configMapRepository) @@ -166,8 +173,10 @@ func main() { CertificateRepository: certificateRepository, ConfigMapRepository: configMapRepository, DeploymentRepository: deploymentRepository, + JobRepository: jobRepository, ServiceRepository: serviceRepository, SecretRepository: secretRepository, + VirtualmachineRepository: virtualMachineRepository, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "OSBuildEnvConfig") os.Exit(1) diff --git a/resources/ansible/requirements.yml b/resources/ansible/requirements.yml new file mode 100644 index 00000000..72fe72df --- /dev/null +++ b/resources/ansible/requirements.yml @@ -0,0 +1,2 @@ +collections: + - name: community.general diff --git a/resources/templates/composer-proxy-config.yaml b/resources/templates/composer-proxy-config.yaml index 67ed0111..ada3ea4a 100644 --- a/resources/templates/composer-proxy-config.yaml +++ b/resources/templates/composer-proxy-config.yaml @@ -23,6 +23,7 @@ static_resources: prefix: "/" route: cluster: remote-worker-api + timeout: {{ .ProxyWorkerAPIUpstreamTimeout }} http_filters: - name: envoy.filters.http.router typed_config: diff --git a/resources/templates/worker-config-ansible-config.cfg b/resources/templates/worker-config-ansible-config.cfg new file mode 100644 index 00000000..91fa17e2 --- /dev/null +++ b/resources/templates/worker-config-ansible-config.cfg @@ -0,0 +1,4 @@ +[defaults] +host_key_checking = False +retry_files_enabled = False +callback_whitelist = profile_tasks diff --git a/resources/templates/worker-config-ansible-inventory.yaml b/resources/templates/worker-config-ansible-inventory.yaml new file mode 100644 index 00000000..bd2cb27e --- /dev/null +++ b/resources/templates/worker-config-ansible-inventory.yaml @@ -0,0 +1,6 @@ +all: + hosts: + {{ .Address }}: + ansible_connection: ssh + ansible_user: {{ .User }} + ansible_ssh_private_key_file: {{ .SSHKey }} diff --git a/resources/templates/worker-config-ansible-playbook.yaml b/resources/templates/worker-config-ansible-playbook.yaml new file mode 100644 index 00000000..1d44e2bf --- /dev/null +++ b/resources/templates/worker-config-ansible-playbook.yaml @@ -0,0 +1,166 @@ +- name: Configure OSBuild Worker Machine + hosts: all + vars: + rpmrepo_distribution: "{{ .RPMRepoDistribution }}" + osbuild_composer_tag: "{{ .OSBuildComposerTag }}" + osbuild_tag: "{{ .OSBuildTag }}" + local_osbuild_certs_dir: "{{ .OSBuildWorkerCertsDir }}" + osbuild_worker_certificate_directory: "/etc/osbuild-composer" + local_osbuild_config_dir: "{{ .OSBuildWorkerConfigDir }}" + osbuild_worker_config_directory: "/etc/osbuild-worker/" + osbuild_worker_config_file: "{{ .OSBuildWorkerConfigFile }}" + osbuild_worker_s3_creds_file: "{{ .OSBuildWorkerS3CredsFile }}" + osbuild_worker_s3_ca_bundle_file: "{{ .OSBuildWorkerS3CABundleFile }}" + gather_facts: yes + become: yes + tasks: + - name: Get RH Credentials + delegate_to: localhost + become: no + no_log: True + block: + - name: Get RH User + slurp: + src: {{"'{{ item }}'"}} + register: cred_files_content + loop: + - "{{ .RHCredentialsDir }}/{{ .RHCredentialsUsernameKey }}" + - "{{ .RHCredentialsDir }}/{{ .RHCredentialsPasswordKey }}" + - set_fact: + rh_username: {{"'{{ cred_files_content.results[0].content | b64decode}}'"}} + rh_password: {{"'{{ cred_files_content.results[1].content | b64decode}}'"}} + - name: Get commit hashes from tags + delegate_to: localhost + become: no + block: + - name: Get osbuild-composer releases + uri: + url: "https://api.github.com/repos/osbuild/osbuild-composer/tags" + register: composer_releases + - name: Get osbuild releases + uri: + url: "https://api.github.com/repos/osbuild/osbuild/tags" + register: osbuild_releases + - set_fact: + composer_release: {{"\"{{ composer_releases.json | selectattr('name', '==', osbuild_composer_tag)| first }}\""}} + osbuild_release: {{"\"{{ osbuild_releases.json | selectattr('name', '==', osbuild_tag)| first }}\""}} + - name: Register the machine with RH + community.general.packaging.os.redhat_subscription: + state: present + username: {{"'{{ rh_username }}'"}} + password: {{"'{{ rh_password }}'"}} + auto_attach: true + retries: 3 + delay: 5 + - name: Add osbuild-composer repository + tags: + - rpmrepo + yum_repository: + name: "composer" + description: {{"'osbuild-composer commit {{ composer_release.commit.sha }}'"}} + baseurl: {{"'http://osbuild-composer-repos.s3.amazonaws.com/osbuild-composer/{{ rpmrepo_distribution }}/{{ ansible_architecture }}/{{ composer_release.commit.sha }}'"}} + enabled: yes + gpgcheck: no + priority: "5" + + - name: Add osbuild repository + tags: + - rpmrepo + yum_repository: + name: "osbuild" + description: {{"'osbuild commit {{ osbuild_release.commit.sha }}'"}} + baseurl: {{"'http://osbuild-composer-repos.s3-website.us-east-2.amazonaws.com/osbuild/{{ rpmrepo_distribution }}/{{ ansible_architecture }}/{{ osbuild_release.commit.sha }}'"}} + enabled: yes + gpgcheck: no + priority: "5" + + - name: Upgrade all packages + package: + name: "*" + state: latest + register: result + retries: 5 + until: result is success + + - name: Install worker rpm + package: + name: + - osbuild-composer-worker + state: present + + - name: Copy OSBuild Worker Certificates + block: + - name: Create certificate directory + ansible.builtin.file: + path: {{"'{{ osbuild_worker_certificate_directory }}'"}} + state: directory + mode: '0755' + - name: Copy the certificates + ansible.builtin.copy: + src: {{"'{{ local_osbuild_certs_dir }}/{{ item.src }}'"}} + dest: {{"'{{ osbuild_worker_certificate_directory }}/{{ item.dest }}'"}} + mode: '0400' + loop: + - src: ca.crt + dest: ca-crt.pem + - src: tls.crt + dest: worker-crt.pem + - src: tls.key + dest: worker-key.pem + + - name: Create osbuild-worker etc dir + ansible.builtin.file: + path: {{"'{{ osbuild_worker_config_directory }}'"}} + state: directory + mode: '0755' + + - name: Copy the OSBuild-Worker configuration file + ansible.builtin.copy: + src: {{"'{{ local_osbuild_config_dir }}/{{ osbuild_worker_config_file }}'"}} + dest: {{"'{{ osbuild_worker_config_directory }}/{{ osbuild_worker_config_file }}'"}} + mode: '0400' + + - name: Create the S3 Credentials file + no_log: True + block: + - name: Get the credentials from the local files + delegate_to: localhost + become: no + block: + - name: Read the credential files + slurp: + src: {{"'{{ item }}'"}} + register: s3_cred_files_content + loop: + - "{{ .OSBuildWorkerS3CredsDir }}/{{ .OSBuildWorkerS3CredsAccessKeyIDKey }}" + - "{{ .OSBuildWorkerS3CredsDir }}/{{ .OSBuildWorkerS3CredsSecretAccessKeyKey }}" + - set_fact: + s3_creds_access_key_id: {{"'{{ s3_cred_files_content.results[0].content | b64decode}}'"}} + s3_creds_secret_access_key: {{"'{{ s3_cred_files_content.results[1].content | b64decode}}'"}} + - name: Write the credentials to the file + ansible.builtin.copy: + content: | + [default] + aws_access_key_id = {{"{{ s3_creds_access_key_id }}"}} + aws_secret_access_key = {{"{{ s3_creds_secret_access_key }}"}} + dest: {{"'{{ osbuild_worker_config_directory }}/{{ osbuild_worker_s3_creds_file }}'"}} + mode: '0400' + + - name: Handle S3 CA Bundle file + block: + - name: Check if exists + delegate_to: localhost + become: no + ansible.builtin.stat: + path: "{{ .OSBuildWorkerS3CABundleDir }}/{{ .OSBuildWorkerS3CABundleKey }}" + register: ca_bundle_file + - name: Copy the S3 CA Bundle file if exists + ansible.builtin.copy: + src: "{{ .OSBuildWorkerS3CABundleDir }}/{{ .OSBuildWorkerS3CABundleKey }}" + dest: {{"'{{ osbuild_worker_config_directory }}/{{ osbuild_worker_s3_ca_bundle_file }}'"}} + when: ca_bundle_file.stat.exists + + - name: Run the Worker + ansible.builtin.systemd: + state: started + name: "osbuild-remote-worker@{{ .ComposerWorkerAPIServiceName }}:443" diff --git a/resources/templates/worker-osbuild-worker-config.toml b/resources/templates/worker-osbuild-worker-config.toml new file mode 100644 index 00000000..f9ffd682 --- /dev/null +++ b/resources/templates/worker-osbuild-worker-config.toml @@ -0,0 +1,19 @@ +{{- if .GenericS3 }} +[generic_s3] +{{- else }} +[aws] +{{- end }} +credentials = "/etc/osbuild-worker/{{ .CredentialsFile }}" +bucket = "{{ .Bucket }}" +{{- if .GenericS3 }} +endpoint = "{{ .GenericS3.Endpoint }}" +region = "{{ .GenericS3.Region }}" +{{- if .GenericS3.CABundleFile }} +ca_bundle = "/etc/osbuild-worker/{{ .GenericS3.CABundleFile }}" +{{- end }} +{{- if .GenericS3.SkipSSLVerification }} +skip_ssl_verification = {{ .GenericS3.SkipSSLVerification }} +{{- else }} +skip_ssl_verification = false +{{- end }} +{{- end }} diff --git a/resources/templates/worker-setup-job.yaml b/resources/templates/worker-setup-job.yaml new file mode 100644 index 00000000..e4d2729b --- /dev/null +++ b/resources/templates/worker-setup-job.yaml @@ -0,0 +1,65 @@ +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .WorkerConfigJobNamespace }} + name: {{ .WorkerConfigJobName }} +spec: + template: + spec: + restartPolicy: Never + containers: + - image: "{{ .WorkerConfigJobImageName }}:{{ .WorkerConfigJobImageTag }}" + env: + - name: ANSIBLE_DIR + value: /var/ansible + - name: ANSIBLE_CONFIG + value: $ANSIBLE_DIR/{{ .WorkerConfigAnsibleConfigConfigMapKey }} + command: + - /bin/bash + - -c + - "ansible-playbook -i $ANSIBLE_DIR/{{ .WorkerConfigInventoryConfigMapKey }} $ANSIBLE_DIR/{{ .WorkerConfigPlaybookConfigMapKey }}" + volumeMounts: + - name: ssh-key + mountPath: {{ .WorkerConfigJobSSHKeyDir }} + readOnly: true + - name: ansible + mountPath: /var/ansible + readOnly: true + - name: rh-creds + mountPath: {{ .RHCredentialsDir }} + readOnly: true + - name: osbuild-certs + mountPath: {{ .OSBuildWorkerCertsDir }} + readOnly: true + - name: osbuild-config + mountPath: {{ .OSBuildWorkerConfigDir }} + - name: s3-creds + mountPath: {{ .OSBuildWorkerS3CredsDir }} + imagePullPolicy: Always + name: ansible + volumes: + - name: ssh-key + secret: + secretName: {{ .WorkerSSHKeysSecretName }} + defaultMode: 0400 + - name: ansible + projected: + sources: + - configMap: + name: {{ .WorkerConfigAnsibleConfigConfigMapName }} + - configMap: + name: {{ .WorkerConfigPlaybookConfigMapName }} + - configMap: + name: {{ .WorkerConfigInventoryConfigMapName }} + - name: rh-creds + secret: + secretName: {{ .RedHatCredsSecretName }} + - name: osbuild-certs + secret: + secretName: {{ .WorkerCertificateName }} + - name: osbuild-config + configMap: + name: {{ .WorkerOSBuildWorkerConfigConfigMapName }} + - name: s3-creds + secret: + secretName: {{ .WorkerS3CredsSecretName }} diff --git a/resources/templates/worker-vm.yaml b/resources/templates/worker-vm.yaml new file mode 100644 index 00000000..70b9065c --- /dev/null +++ b/resources/templates/worker-vm.yaml @@ -0,0 +1,95 @@ +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + annotations: + description: OSBuild Worker + name.os.template.kubevirt.io/rhel8.5: "Red Hat Enterprise Linux 8.0 or higher" + labels: + app: osbuild-worker + workload.template.kubevirt.io/server: "true" + os.template.kubevirt.io/rhel8.5: "true" + namespace: {{ .Namespace }} + name: {{ .Name }} +spec: + dataVolumeTemplates: + - apiVersion: cdi.kubevirt.io/v1alpha1 + kind: DataVolume + metadata: + creationTimestamp: null + name: image-builder-rootdisk + spec: + pvc: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + volumeMode: Filesystem + source: + http: + url: {{ .ImageURL }} + runStrategy: Always + template: + metadata: + labels: + app: osbuild-worker + kubevirt.io/domain: osbuild-worker + vm.kubevirt.io/name: osbuild-worker + workload.template.kubevirt.io/server: "true" + os.template.kubevirt.io/rhel8.5: 'true' + osbuild-worker: {{ .Name }} + spec: + domain: + cpu: + cores: 4 + sockets: 1 + threads: 1 + devices: + disks: + - bootOrder: 1 + disk: + bus: virtio + name: rootdisk + - disk: + bus: virtio + name: cloudinitdisk + - disk: + bus: virtio + name: ssh-keys + serial: ibsk + interfaces: + - masquerade: {} + model: virtio + name: nic-0 + networkInterfaceMultiqueue: true + rng: {} + machine: + type: pc-q35-rhel8.4.0 + resources: + requests: + memory: 8Gi + hostname: {{ .Hostname }} + networks: + - name: nic-0 + pod: {} + terminationGracePeriodSeconds: 180 + volumes: + - dataVolume: + name: image-builder-rootdisk + name: rootdisk + - cloudInitNoCloud: + userData: | + #cloud-config + name: default + hostname: {{ .Hostname }} + user: {{ .Username }} + bootcmd: + - "mkdir -p /home/{{ .Username }}/.ssh && chown -R 1000:1000 /home/{{ .Username }}" + - "mkdir -p /var/secrets/ssh-keys" + - "mount -o overriderockperm,mode=0400,uid=0,gid=0 /dev/disk/by-id/virtio-ibsk /var/secrets/ssh-keys" + - "cp /var/secrets/ssh-keys/ssh-publickey /home/cloud-user/.ssh/authorized_keys" + - "chmod 644 /home/{{ .Username }}/.ssh/authorized_keys" + name: cloudinitdisk + - name: ssh-keys + secret: + secretName: {{ .SSHKeysSecretName }} diff --git a/vendor/github.com/openshift/custom-resource-status/LICENSE b/vendor/github.com/openshift/custom-resource-status/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/vendor/github.com/openshift/custom-resource-status/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go new file mode 100644 index 00000000..bbeee804 --- /dev/null +++ b/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go @@ -0,0 +1,104 @@ +package v1 + +import ( + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SetStatusCondition sets the corresponding condition in conditions to newCondition. +func SetStatusCondition(conditions *[]Condition, newCondition Condition) { + if conditions == nil { + conditions = &[]Condition{} + } + existingCondition := FindStatusCondition(*conditions, newCondition.Type) + if existingCondition == nil { + newCondition.LastTransitionTime = metav1.NewTime(time.Now()) + newCondition.LastHeartbeatTime = metav1.NewTime(time.Now()) + *conditions = append(*conditions, newCondition) + return + } + + if existingCondition.Status != newCondition.Status { + existingCondition.Status = newCondition.Status + existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) + } + + existingCondition.Reason = newCondition.Reason + existingCondition.Message = newCondition.Message + existingCondition.LastHeartbeatTime = metav1.NewTime(time.Now()) +} + +// SetStatusConditionNoHearbeat sets the corresponding condition in conditions to newCondition +// without setting lastHeartbeatTime. +func SetStatusConditionNoHeartbeat(conditions *[]Condition, newCondition Condition) { + if conditions == nil { + conditions = &[]Condition{} + } + existingCondition := FindStatusCondition(*conditions, newCondition.Type) + if existingCondition == nil { + newCondition.LastTransitionTime = metav1.NewTime(time.Now()) + *conditions = append(*conditions, newCondition) + return + } + + if existingCondition.Status != newCondition.Status { + existingCondition.Status = newCondition.Status + existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) + } + + existingCondition.Reason = newCondition.Reason + existingCondition.Message = newCondition.Message +} + +// RemoveStatusCondition removes the corresponding conditionType from conditions. +func RemoveStatusCondition(conditions *[]Condition, conditionType ConditionType) { + if conditions == nil { + return + } + newConditions := []Condition{} + for _, condition := range *conditions { + if condition.Type != conditionType { + newConditions = append(newConditions, condition) + } + } + + *conditions = newConditions +} + +// FindStatusCondition finds the conditionType in conditions. +func FindStatusCondition(conditions []Condition, conditionType ConditionType) *Condition { + for i := range conditions { + if conditions[i].Type == conditionType { + return &conditions[i] + } + } + + return nil +} + +// IsStatusConditionTrue returns true when the conditionType is present and set to `corev1.ConditionTrue` +func IsStatusConditionTrue(conditions []Condition, conditionType ConditionType) bool { + return IsStatusConditionPresentAndEqual(conditions, conditionType, corev1.ConditionTrue) +} + +// IsStatusConditionFalse returns true when the conditionType is present and set to `corev1.ConditionFalse` +func IsStatusConditionFalse(conditions []Condition, conditionType ConditionType) bool { + return IsStatusConditionPresentAndEqual(conditions, conditionType, corev1.ConditionFalse) +} + +// IsStatusConditionUnknown returns true when the conditionType is present and set to `corev1.ConditionUnknown` +func IsStatusConditionUnknown(conditions []Condition, conditionType ConditionType) bool { + return IsStatusConditionPresentAndEqual(conditions, conditionType, corev1.ConditionUnknown) +} + +// IsStatusConditionPresentAndEqual returns true when conditionType is present and equal to status. +func IsStatusConditionPresentAndEqual(conditions []Condition, conditionType ConditionType, status corev1.ConditionStatus) bool { + for _, condition := range conditions { + if condition.Type == conditionType { + return condition.Status == status + } + } + return false +} diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go new file mode 100644 index 00000000..b657efea --- /dev/null +++ b/vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go @@ -0,0 +1,9 @@ +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +k8s:openapi-gen=true + +// Package v1 provides version v1 of the types and functions necessary to +// manage and inspect a slice of conditions. It is opinionated in the +// condition types provided but leaves it to the user to define additional +// types as necessary. +package v1 diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go new file mode 100644 index 00000000..950678fb --- /dev/null +++ b/vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go @@ -0,0 +1,51 @@ +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Condition represents the state of the operator's +// reconciliation functionality. +// +k8s:deepcopy-gen=true +type Condition struct { + Type ConditionType `json:"type" description:"type of condition ie. Available|Progressing|Degraded."` + + Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` + + // +optional + Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` + + // +optional + Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` + + // +optional + LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime" description:"last time we got an update on a given condition"` + + // +optional + LastTransitionTime metav1.Time `json:"lastTransitionTime" description:"last time the condition transit from one status to another"` +} + +// ConditionType is the state of the operator's reconciliation functionality. +type ConditionType string + +const ( + // ConditionAvailable indicates that the resources maintained by the operator, + // is functional and available in the cluster. + ConditionAvailable ConditionType = "Available" + + // ConditionProgressing indicates that the operator is actively making changes to the resources maintained by the + // operator + ConditionProgressing ConditionType = "Progressing" + + // ConditionDegraded indicates that the resources maintained by the operator are not functioning completely. + // An example of a degraded state would be if not all pods in a deployment were running. + // It may still be available, but it is degraded + ConditionDegraded ConditionType = "Degraded" + + // ConditionUpgradeable indicates whether the resources maintained by the operator are in a state that is safe to upgrade. + // When `False`, the resources maintained by the operator should not be upgraded and the + // message field should contain a human readable description of what the administrator should do to + // allow the operator to successfully update the resources maintained by the operator. + ConditionUpgradeable ConditionType = "Upgradeable" +) diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000..bbbbf863 --- /dev/null +++ b/vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go @@ -0,0 +1,23 @@ +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastHeartbeatTime.DeepCopyInto(&out.LastHeartbeatTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/pborman/uuid/.travis.yml b/vendor/github.com/pborman/uuid/.travis.yml new file mode 100644 index 00000000..3deb4a12 --- /dev/null +++ b/vendor/github.com/pborman/uuid/.travis.yml @@ -0,0 +1,10 @@ +language: go + +go: + - "1.9" + - "1.10" + - "1.11" + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/pborman/uuid/CONTRIBUTING.md b/vendor/github.com/pborman/uuid/CONTRIBUTING.md new file mode 100644 index 00000000..04fdf09f --- /dev/null +++ b/vendor/github.com/pborman/uuid/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# How to contribute + +We definitely welcome patches and contribution to this project! + +### Legal requirements + +In order to protect both you and ourselves, you will need to sign the +[Contributor License Agreement](https://cla.developers.google.com/clas). + +You may have already signed it for other Google projects. diff --git a/vendor/github.com/pborman/uuid/CONTRIBUTORS b/vendor/github.com/pborman/uuid/CONTRIBUTORS new file mode 100644 index 00000000..b382a04e --- /dev/null +++ b/vendor/github.com/pborman/uuid/CONTRIBUTORS @@ -0,0 +1 @@ +Paul Borman diff --git a/vendor/github.com/pborman/uuid/LICENSE b/vendor/github.com/pborman/uuid/LICENSE new file mode 100644 index 00000000..5dc68268 --- /dev/null +++ b/vendor/github.com/pborman/uuid/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009,2014 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md new file mode 100644 index 00000000..810ad40d --- /dev/null +++ b/vendor/github.com/pborman/uuid/README.md @@ -0,0 +1,15 @@ +This project was automatically exported from code.google.com/p/go-uuid + +# uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) +The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. + +This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package). + +###### Install +`go get github.com/pborman/uuid` + +###### Documentation +[![GoDoc](https://godoc.org/github.com/pborman/uuid?status.svg)](http://godoc.org/github.com/pborman/uuid) + +Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: +http://godoc.org/github.com/pborman/uuid diff --git a/vendor/github.com/pborman/uuid/dce.go b/vendor/github.com/pborman/uuid/dce.go new file mode 100644 index 00000000..50a0f2d0 --- /dev/null +++ b/vendor/github.com/pborman/uuid/dce.go @@ -0,0 +1,84 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "fmt" + "os" +) + +// A Domain represents a Version 2 domain +type Domain byte + +// Domain constants for DCE Security (Version 2) UUIDs. +const ( + Person = Domain(0) + Group = Domain(1) + Org = Domain(2) +) + +// NewDCESecurity returns a DCE Security (Version 2) UUID. +// +// The domain should be one of Person, Group or Org. +// On a POSIX system the id should be the users UID for the Person +// domain and the users GID for the Group. The meaning of id for +// the domain Org or on non-POSIX systems is site defined. +// +// For a given domain/id pair the same token may be returned for up to +// 7 minutes and 10 seconds. +func NewDCESecurity(domain Domain, id uint32) UUID { + uuid := NewUUID() + if uuid != nil { + uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 + uuid[9] = byte(domain) + binary.BigEndian.PutUint32(uuid[0:], id) + } + return uuid +} + +// NewDCEPerson returns a DCE Security (Version 2) UUID in the person +// domain with the id returned by os.Getuid. +// +// NewDCEPerson(Person, uint32(os.Getuid())) +func NewDCEPerson() UUID { + return NewDCESecurity(Person, uint32(os.Getuid())) +} + +// NewDCEGroup returns a DCE Security (Version 2) UUID in the group +// domain with the id returned by os.Getgid. +// +// NewDCEGroup(Group, uint32(os.Getgid())) +func NewDCEGroup() UUID { + return NewDCESecurity(Group, uint32(os.Getgid())) +} + +// Domain returns the domain for a Version 2 UUID or false. +func (uuid UUID) Domain() (Domain, bool) { + if v, _ := uuid.Version(); v != 2 { + return 0, false + } + return Domain(uuid[9]), true +} + +// Id returns the id for a Version 2 UUID or false. +func (uuid UUID) Id() (uint32, bool) { + if v, _ := uuid.Version(); v != 2 { + return 0, false + } + return binary.BigEndian.Uint32(uuid[0:4]), true +} + +func (d Domain) String() string { + switch d { + case Person: + return "Person" + case Group: + return "Group" + case Org: + return "Org" + } + return fmt.Sprintf("Domain%d", int(d)) +} diff --git a/vendor/github.com/pborman/uuid/doc.go b/vendor/github.com/pborman/uuid/doc.go new file mode 100644 index 00000000..727d7616 --- /dev/null +++ b/vendor/github.com/pborman/uuid/doc.go @@ -0,0 +1,13 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The uuid package generates and inspects UUIDs. +// +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// This package is a partial wrapper around the github.com/google/uuid package. +// This package represents a UUID as []byte while github.com/google/uuid +// represents a UUID as [16]byte. +package uuid diff --git a/vendor/github.com/pborman/uuid/hash.go b/vendor/github.com/pborman/uuid/hash.go new file mode 100644 index 00000000..a0420c1e --- /dev/null +++ b/vendor/github.com/pborman/uuid/hash.go @@ -0,0 +1,53 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "crypto/md5" + "crypto/sha1" + "hash" +) + +// Well known Name Space IDs and UUIDs +var ( + NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8") + NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8") + NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8") + NIL = Parse("00000000-0000-0000-0000-000000000000") +) + +// NewHash returns a new UUID derived from the hash of space concatenated with +// data generated by h. The hash should be at least 16 byte in length. The +// first 16 bytes of the hash are used to form the UUID. The version of the +// UUID will be the lower 4 bits of version. NewHash is used to implement +// NewMD5 and NewSHA1. +func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { + h.Reset() + h.Write(space) + h.Write([]byte(data)) + s := h.Sum(nil) + uuid := make([]byte, 16) + copy(uuid, s) + uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) + uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant + return uuid +} + +// NewMD5 returns a new MD5 (Version 3) UUID based on the +// supplied name space and data. +// +// NewHash(md5.New(), space, data, 3) +func NewMD5(space UUID, data []byte) UUID { + return NewHash(md5.New(), space, data, 3) +} + +// NewSHA1 returns a new SHA1 (Version 5) UUID based on the +// supplied name space and data. +// +// NewHash(sha1.New(), space, data, 5) +func NewSHA1(space UUID, data []byte) UUID { + return NewHash(sha1.New(), space, data, 5) +} diff --git a/vendor/github.com/pborman/uuid/marshal.go b/vendor/github.com/pborman/uuid/marshal.go new file mode 100644 index 00000000..35b89352 --- /dev/null +++ b/vendor/github.com/pborman/uuid/marshal.go @@ -0,0 +1,85 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "errors" + "fmt" + + guuid "github.com/google/uuid" +) + +// MarshalText implements encoding.TextMarshaler. +func (u UUID) MarshalText() ([]byte, error) { + if len(u) != 16 { + return nil, nil + } + var js [36]byte + encodeHex(js[:], u) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (u *UUID) UnmarshalText(data []byte) error { + if len(data) == 0 { + return nil + } + id := Parse(string(data)) + if id == nil { + return errors.New("invalid UUID") + } + *u = id + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (u UUID) MarshalBinary() ([]byte, error) { + return u[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (u *UUID) UnmarshalBinary(data []byte) error { + if len(data) == 0 { + return nil + } + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + var id [16]byte + copy(id[:], data) + *u = id[:] + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (u Array) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], u[:]) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (u *Array) UnmarshalText(data []byte) error { + id, err := guuid.ParseBytes(data) + if err != nil { + return err + } + *u = Array(id) + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (u Array) MarshalBinary() ([]byte, error) { + return u[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (u *Array) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(u[:], data) + return nil +} diff --git a/vendor/github.com/pborman/uuid/node.go b/vendor/github.com/pborman/uuid/node.go new file mode 100644 index 00000000..e524e010 --- /dev/null +++ b/vendor/github.com/pborman/uuid/node.go @@ -0,0 +1,50 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + guuid "github.com/google/uuid" +) + +// NodeInterface returns the name of the interface from which the NodeID was +// derived. The interface "user" is returned if the NodeID was set by +// SetNodeID. +func NodeInterface() string { + return guuid.NodeInterface() +} + +// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. +// If name is "" then the first usable interface found will be used or a random +// Node ID will be generated. If a named interface cannot be found then false +// is returned. +// +// SetNodeInterface never fails when name is "". +func SetNodeInterface(name string) bool { + return guuid.SetNodeInterface(name) +} + +// NodeID returns a slice of a copy of the current Node ID, setting the Node ID +// if not already set. +func NodeID() []byte { + return guuid.NodeID() +} + +// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes +// of id are used. If id is less than 6 bytes then false is returned and the +// Node ID is not set. +func SetNodeID(id []byte) bool { + return guuid.SetNodeID(id) +} + +// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is +// not valid. The NodeID is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) NodeID() []byte { + if len(uuid) != 16 { + return nil + } + node := make([]byte, 6) + copy(node, uuid[10:]) + return node +} diff --git a/vendor/github.com/pborman/uuid/sql.go b/vendor/github.com/pborman/uuid/sql.go new file mode 100644 index 00000000..929c3847 --- /dev/null +++ b/vendor/github.com/pborman/uuid/sql.go @@ -0,0 +1,68 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "database/sql/driver" + "errors" + "fmt" +) + +// Scan implements sql.Scanner so UUIDs can be read from databases transparently +// Currently, database types that map to string and []byte are supported. Please +// consult database-specific driver documentation for matching types. +func (uuid *UUID) Scan(src interface{}) error { + switch src.(type) { + case string: + // if an empty UUID comes from a table, we return a null UUID + if src.(string) == "" { + return nil + } + + // see uuid.Parse for required string format + parsed := Parse(src.(string)) + + if parsed == nil { + return errors.New("Scan: invalid UUID format") + } + + *uuid = parsed + case []byte: + b := src.([]byte) + + // if an empty UUID comes from a table, we return a null UUID + if len(b) == 0 { + return nil + } + + // assumes a simple slice of bytes if 16 bytes + // otherwise attempts to parse + if len(b) == 16 { + parsed := make([]byte, 16) + copy(parsed, b) + *uuid = UUID(parsed) + } else { + u := Parse(string(b)) + + if u == nil { + return errors.New("Scan: invalid UUID format") + } + + *uuid = u + } + + default: + return fmt.Errorf("Scan: unable to scan type %T into UUID", src) + } + + return nil +} + +// Value implements sql.Valuer so that UUIDs can be written to databases +// transparently. Currently, UUIDs map to strings. Please consult +// database-specific driver documentation for matching types. +func (uuid UUID) Value() (driver.Value, error) { + return uuid.String(), nil +} diff --git a/vendor/github.com/pborman/uuid/time.go b/vendor/github.com/pborman/uuid/time.go new file mode 100644 index 00000000..5c0960d8 --- /dev/null +++ b/vendor/github.com/pborman/uuid/time.go @@ -0,0 +1,57 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + + guuid "github.com/google/uuid" +) + +// A Time represents a time as the number of 100's of nanoseconds since 15 Oct +// 1582. +type Time = guuid.Time + +// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and +// clock sequence as well as adjusting the clock sequence as needed. An error +// is returned if the current time cannot be determined. +func GetTime() (Time, uint16, error) { return guuid.GetTime() } + +// ClockSequence returns the current clock sequence, generating one if not +// already set. The clock sequence is only used for Version 1 UUIDs. +// +// The uuid package does not use global static storage for the clock sequence or +// the last time a UUID was generated. Unless SetClockSequence a new random +// clock sequence is generated the first time a clock sequence is requested by +// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated +// for +func ClockSequence() int { return guuid.ClockSequence() } + +// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to +// -1 causes a new sequence to be generated. +func SetClockSequence(seq int) { guuid.SetClockSequence(seq) } + +// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in +// uuid. It returns false if uuid is not valid. The time is only well defined +// for version 1 and 2 UUIDs. +func (uuid UUID) Time() (Time, bool) { + if len(uuid) != 16 { + return 0, false + } + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + return Time(time), true +} + +// ClockSequence returns the clock sequence encoded in uuid. It returns false +// if uuid is not valid. The clock sequence is only well defined for version 1 +// and 2 UUIDs. +func (uuid UUID) ClockSequence() (int, bool) { + if len(uuid) != 16 { + return 0, false + } + return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true +} diff --git a/vendor/github.com/pborman/uuid/util.go b/vendor/github.com/pborman/uuid/util.go new file mode 100644 index 00000000..255b5e24 --- /dev/null +++ b/vendor/github.com/pborman/uuid/util.go @@ -0,0 +1,32 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +// xvalues returns the value of a byte as a hexadecimal digit or 255. +var xvalues = [256]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +} + +// xtob converts the the first two hex bytes of x into a byte. +func xtob(x string) (byte, bool) { + b1 := xvalues[x[0]] + b2 := xvalues[x[1]] + return (b1 << 4) | b2, b1 != 255 && b2 != 255 +} diff --git a/vendor/github.com/pborman/uuid/uuid.go b/vendor/github.com/pborman/uuid/uuid.go new file mode 100644 index 00000000..33700042 --- /dev/null +++ b/vendor/github.com/pborman/uuid/uuid.go @@ -0,0 +1,162 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "io" + + guuid "github.com/google/uuid" +) + +// Array is a pass-by-value UUID that can be used as an effecient key in a map. +type Array [16]byte + +// UUID converts uuid into a slice. +func (uuid Array) UUID() UUID { + return uuid[:] +} + +// String returns the string representation of uuid, +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. +func (uuid Array) String() string { + return guuid.UUID(uuid).String() +} + +// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC +// 4122. +type UUID []byte + +// A Version represents a UUIDs version. +type Version = guuid.Version + +// A Variant represents a UUIDs variant. +type Variant = guuid.Variant + +// Constants returned by Variant. +const ( + Invalid = guuid.Invalid // Invalid UUID + RFC4122 = guuid.RFC4122 // The variant specified in RFC4122 + Reserved = guuid.Reserved // Reserved, NCS backward compatibility. + Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future = guuid.Future // Reserved for future definition. +) + +var rander = rand.Reader // random function + +// New returns a new random (version 4) UUID as a string. It is a convenience +// function for NewRandom().String(). +func New() string { + return NewRandom().String() +} + +// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for +// the formats parsed. +func Parse(s string) UUID { + gu, err := guuid.Parse(s) + if err == nil { + return gu[:] + } + return nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + gu, err := guuid.ParseBytes(b) + if err == nil { + return gu[:], nil + } + return nil, err +} + +// Equal returns true if uuid1 and uuid2 are equal. +func Equal(uuid1, uuid2 UUID) bool { + return bytes.Equal(uuid1, uuid2) +} + +// Array returns an array representation of uuid that can be used as a map key. +// Array panics if uuid is not valid. +func (uuid UUID) Array() Array { + if len(uuid) != 16 { + panic("invalid uuid") + } + var a Array + copy(a[:], uuid) + return a +} + +// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// , or "" if uuid is invalid. +func (uuid UUID) String() string { + if len(uuid) != 16 { + return "" + } + var buf [36]byte + encodeHex(buf[:], uuid) + return string(buf[:]) +} + +// URN returns the RFC 2141 URN form of uuid, +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. +func (uuid UUID) URN() string { + if len(uuid) != 16 { + return "" + } + var buf [36 + 9]byte + copy(buf[:], "urn:uuid:") + encodeHex(buf[9:], uuid) + return string(buf[:]) +} + +func encodeHex(dst []byte, uuid UUID) { + hex.Encode(dst[:], uuid[:4]) + dst[8] = '-' + hex.Encode(dst[9:13], uuid[4:6]) + dst[13] = '-' + hex.Encode(dst[14:18], uuid[6:8]) + dst[18] = '-' + hex.Encode(dst[19:23], uuid[8:10]) + dst[23] = '-' + hex.Encode(dst[24:], uuid[10:]) +} + +// Variant returns the variant encoded in uuid. It returns Invalid if +// uuid is invalid. +func (uuid UUID) Variant() Variant { + if len(uuid) != 16 { + return Invalid + } + switch { + case (uuid[8] & 0xc0) == 0x80: + return RFC4122 + case (uuid[8] & 0xe0) == 0xc0: + return Microsoft + case (uuid[8] & 0xe0) == 0xe0: + return Future + default: + return Reserved + } +} + +// Version returns the version of uuid. It returns false if uuid is not +// valid. +func (uuid UUID) Version() (Version, bool) { + if len(uuid) != 16 { + return 0, false + } + return Version(uuid[6] >> 4), true +} + +// SetRand sets the random number generator to r, which implements io.Reader. +// If r.Read returns an error when the package requests random data then +// a panic will be issued. +// +// Calling SetRand with nil sets the random number generator to the default +// generator. +func SetRand(r io.Reader) { + guuid.SetRand(r) +} diff --git a/vendor/github.com/pborman/uuid/version1.go b/vendor/github.com/pborman/uuid/version1.go new file mode 100644 index 00000000..7af948da --- /dev/null +++ b/vendor/github.com/pborman/uuid/version1.go @@ -0,0 +1,23 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + guuid "github.com/google/uuid" +) + +// NewUUID returns a Version 1 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewUUID returns nil. If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewUUID returns nil. +func NewUUID() UUID { + gu, err := guuid.NewUUID() + if err == nil { + return UUID(gu[:]) + } + return nil +} diff --git a/vendor/github.com/pborman/uuid/version4.go b/vendor/github.com/pborman/uuid/version4.go new file mode 100644 index 00000000..b459d46d --- /dev/null +++ b/vendor/github.com/pborman/uuid/version4.go @@ -0,0 +1,26 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import guuid "github.com/google/uuid" + +// Random returns a Random (Version 4) UUID or panics. +// +// The strength of the UUIDs is based on the strength of the crypto/rand +// package. +// +// A note about uniqueness derived from the UUID Wikipedia entry: +// +// Randomly generated UUIDs have 122 random bits. One's annual risk of being +// hit by a meteorite is estimated to be one chance in 17 billion, that +// means the probability is about 0.00000000006 (6 × 10−11), +// equivalent to the odds of creating a few tens of trillions of UUIDs in a +// year and having one duplicate. +func NewRandom() UUID { + if gu, err := guuid.NewRandom(); err == nil { + return UUID(gu[:]) + } + return nil +} diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go new file mode 100644 index 00000000..9d80f195 --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/block.go @@ -0,0 +1,159 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blowfish + +// getNextWord returns the next big-endian uint32 value from the byte slice +// at the given position in a circular manner, updating the position. +func getNextWord(b []byte, pos *int) uint32 { + var w uint32 + j := *pos + for i := 0; i < 4; i++ { + w = w<<8 | uint32(b[j]) + j++ + if j >= len(b) { + j = 0 + } + } + *pos = j + return w +} + +// ExpandKey performs a key expansion on the given *Cipher. Specifically, it +// performs the Blowfish algorithm's key schedule which sets up the *Cipher's +// pi and substitution tables for calls to Encrypt. This is used, primarily, +// by the bcrypt package to reuse the Blowfish key schedule during its +// set up. It's unlikely that you need to use this directly. +func ExpandKey(key []byte, c *Cipher) { + j := 0 + for i := 0; i < 18; i++ { + // Using inlined getNextWord for performance. + var d uint32 + for k := 0; k < 4; k++ { + d = d<<8 | uint32(key[j]) + j++ + if j >= len(key) { + j = 0 + } + } + c.p[i] ^= d + } + + var l, r uint32 + for i := 0; i < 18; i += 2 { + l, r = encryptBlock(l, r, c) + c.p[i], c.p[i+1] = l, r + } + + for i := 0; i < 256; i += 2 { + l, r = encryptBlock(l, r, c) + c.s0[i], c.s0[i+1] = l, r + } + for i := 0; i < 256; i += 2 { + l, r = encryptBlock(l, r, c) + c.s1[i], c.s1[i+1] = l, r + } + for i := 0; i < 256; i += 2 { + l, r = encryptBlock(l, r, c) + c.s2[i], c.s2[i+1] = l, r + } + for i := 0; i < 256; i += 2 { + l, r = encryptBlock(l, r, c) + c.s3[i], c.s3[i+1] = l, r + } +} + +// This is similar to ExpandKey, but folds the salt during the key +// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero +// salt passed in, reusing ExpandKey turns out to be a place of inefficiency +// and specializing it here is useful. +func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { + j := 0 + for i := 0; i < 18; i++ { + c.p[i] ^= getNextWord(key, &j) + } + + j = 0 + var l, r uint32 + for i := 0; i < 18; i += 2 { + l ^= getNextWord(salt, &j) + r ^= getNextWord(salt, &j) + l, r = encryptBlock(l, r, c) + c.p[i], c.p[i+1] = l, r + } + + for i := 0; i < 256; i += 2 { + l ^= getNextWord(salt, &j) + r ^= getNextWord(salt, &j) + l, r = encryptBlock(l, r, c) + c.s0[i], c.s0[i+1] = l, r + } + + for i := 0; i < 256; i += 2 { + l ^= getNextWord(salt, &j) + r ^= getNextWord(salt, &j) + l, r = encryptBlock(l, r, c) + c.s1[i], c.s1[i+1] = l, r + } + + for i := 0; i < 256; i += 2 { + l ^= getNextWord(salt, &j) + r ^= getNextWord(salt, &j) + l, r = encryptBlock(l, r, c) + c.s2[i], c.s2[i+1] = l, r + } + + for i := 0; i < 256; i += 2 { + l ^= getNextWord(salt, &j) + r ^= getNextWord(salt, &j) + l, r = encryptBlock(l, r, c) + c.s3[i], c.s3[i+1] = l, r + } +} + +func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { + xl, xr := l, r + xl ^= c.p[0] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] + xr ^= c.p[17] + return xr, xl +} + +func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { + xl, xr := l, r + xl ^= c.p[17] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] + xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] + xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] + xr ^= c.p[0] + return xr, xl +} diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go new file mode 100644 index 00000000..213bf204 --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/cipher.go @@ -0,0 +1,99 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. +// +// Blowfish is a legacy cipher and its short block size makes it vulnerable to +// birthday bound attacks (see https://sweet32.info). It should only be used +// where compatibility with legacy systems, not security, is the goal. +// +// Deprecated: any new system should use AES (from crypto/aes, if necessary in +// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from +// golang.org/x/crypto/chacha20poly1305). +package blowfish // import "golang.org/x/crypto/blowfish" + +// The code is a port of Bruce Schneier's C implementation. +// See https://www.schneier.com/blowfish.html. + +import "strconv" + +// The Blowfish block size in bytes. +const BlockSize = 8 + +// A Cipher is an instance of Blowfish encryption using a particular key. +type Cipher struct { + p [18]uint32 + s0, s1, s2, s3 [256]uint32 +} + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) +} + +// NewCipher creates and returns a Cipher. +// The key argument should be the Blowfish key, from 1 to 56 bytes. +func NewCipher(key []byte) (*Cipher, error) { + var result Cipher + if k := len(key); k < 1 || k > 56 { + return nil, KeySizeError(k) + } + initCipher(&result) + ExpandKey(key, &result) + return &result, nil +} + +// NewSaltedCipher creates a returns a Cipher that folds a salt into its key +// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is +// sufficient and desirable. For bcrypt compatibility, the key can be over 56 +// bytes. +func NewSaltedCipher(key, salt []byte) (*Cipher, error) { + if len(salt) == 0 { + return NewCipher(key) + } + var result Cipher + if k := len(key); k < 1 { + return nil, KeySizeError(k) + } + initCipher(&result) + expandKeyWithSalt(key, salt, &result) + return &result, nil +} + +// BlockSize returns the Blowfish block size, 8 bytes. +// It is necessary to satisfy the Block interface in the +// package "crypto/cipher". +func (c *Cipher) BlockSize() int { return BlockSize } + +// Encrypt encrypts the 8-byte buffer src using the key k +// and stores the result in dst. +// Note that for amounts of data larger than a block, +// it is not safe to just call Encrypt on successive blocks; +// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). +func (c *Cipher) Encrypt(dst, src []byte) { + l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) + r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) + l, r = encryptBlock(l, r, c) + dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) + dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) +} + +// Decrypt decrypts the 8-byte buffer src using the key k +// and stores the result in dst. +func (c *Cipher) Decrypt(dst, src []byte) { + l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) + r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) + l, r = decryptBlock(l, r, c) + dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) + dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) +} + +func initCipher(c *Cipher) { + copy(c.p[0:], p[0:]) + copy(c.s0[0:], s0[0:]) + copy(c.s1[0:], s1[0:]) + copy(c.s2[0:], s2[0:]) + copy(c.s3[0:], s3[0:]) +} diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go new file mode 100644 index 00000000..d0407759 --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/const.go @@ -0,0 +1,199 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The startup permutation array and substitution boxes. +// They are the hexadecimal digits of PI; see: +// https://www.schneier.com/code/constants.txt. + +package blowfish + +var s0 = [256]uint32{ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, +} + +var s1 = [256]uint32{ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, +} + +var s2 = [256]uint32{ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, +} + +var s3 = [256]uint32{ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, +} + +var p = [18]uint32{ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go new file mode 100644 index 00000000..94c71ac1 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go @@ -0,0 +1,17 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.11 && gc && !purego +// +build go1.11,gc,!purego + +package chacha20 + +const bufSize = 256 + +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s new file mode 100644 index 00000000..63cae9e6 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s @@ -0,0 +1,308 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.11 && gc && !purego +// +build go1.11,gc,!purego + +#include "textflag.h" + +#define NUM_ROUNDS 10 + +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) +TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 + MOVD dst+0(FP), R1 + MOVD src+24(FP), R2 + MOVD src_len+32(FP), R3 + MOVD key+48(FP), R4 + MOVD nonce+56(FP), R6 + MOVD counter+64(FP), R7 + + MOVD $·constants(SB), R10 + MOVD $·incRotMatrix(SB), R11 + + MOVW (R7), R20 + + AND $~255, R3, R13 + ADD R2, R13, R12 // R12 for block end + AND $255, R3, R13 +loop: + MOVD $NUM_ROUNDS, R21 + VLD1 (R11), [V30.S4, V31.S4] + + // load contants + // VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] + WORD $0x4D60E940 + + // load keys + // VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4] + WORD $0x4DFFE884 + // VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4] + WORD $0x4DFFE888 + SUB $32, R4 + + // load counter + nonce + // VLD1R (R7), [V12.S4] + WORD $0x4D40C8EC + + // VLD3R (R6), [V13.S4, V14.S4, V15.S4] + WORD $0x4D40E8CD + + // update counter + VADD V30.S4, V12.S4, V12.S4 + +chacha: + // V0..V3 += V4..V7 + // V12..V15 <<<= ((V12..V15 XOR V0..V3), 16) + VADD V0.S4, V4.S4, V0.S4 + VADD V1.S4, V5.S4, V1.S4 + VADD V2.S4, V6.S4, V2.S4 + VADD V3.S4, V7.S4, V3.S4 + VEOR V12.B16, V0.B16, V12.B16 + VEOR V13.B16, V1.B16, V13.B16 + VEOR V14.B16, V2.B16, V14.B16 + VEOR V15.B16, V3.B16, V15.B16 + VREV32 V12.H8, V12.H8 + VREV32 V13.H8, V13.H8 + VREV32 V14.H8, V14.H8 + VREV32 V15.H8, V15.H8 + // V8..V11 += V12..V15 + // V4..V7 <<<= ((V4..V7 XOR V8..V11), 12) + VADD V8.S4, V12.S4, V8.S4 + VADD V9.S4, V13.S4, V9.S4 + VADD V10.S4, V14.S4, V10.S4 + VADD V11.S4, V15.S4, V11.S4 + VEOR V8.B16, V4.B16, V16.B16 + VEOR V9.B16, V5.B16, V17.B16 + VEOR V10.B16, V6.B16, V18.B16 + VEOR V11.B16, V7.B16, V19.B16 + VSHL $12, V16.S4, V4.S4 + VSHL $12, V17.S4, V5.S4 + VSHL $12, V18.S4, V6.S4 + VSHL $12, V19.S4, V7.S4 + VSRI $20, V16.S4, V4.S4 + VSRI $20, V17.S4, V5.S4 + VSRI $20, V18.S4, V6.S4 + VSRI $20, V19.S4, V7.S4 + + // V0..V3 += V4..V7 + // V12..V15 <<<= ((V12..V15 XOR V0..V3), 8) + VADD V0.S4, V4.S4, V0.S4 + VADD V1.S4, V5.S4, V1.S4 + VADD V2.S4, V6.S4, V2.S4 + VADD V3.S4, V7.S4, V3.S4 + VEOR V12.B16, V0.B16, V12.B16 + VEOR V13.B16, V1.B16, V13.B16 + VEOR V14.B16, V2.B16, V14.B16 + VEOR V15.B16, V3.B16, V15.B16 + VTBL V31.B16, [V12.B16], V12.B16 + VTBL V31.B16, [V13.B16], V13.B16 + VTBL V31.B16, [V14.B16], V14.B16 + VTBL V31.B16, [V15.B16], V15.B16 + + // V8..V11 += V12..V15 + // V4..V7 <<<= ((V4..V7 XOR V8..V11), 7) + VADD V12.S4, V8.S4, V8.S4 + VADD V13.S4, V9.S4, V9.S4 + VADD V14.S4, V10.S4, V10.S4 + VADD V15.S4, V11.S4, V11.S4 + VEOR V8.B16, V4.B16, V16.B16 + VEOR V9.B16, V5.B16, V17.B16 + VEOR V10.B16, V6.B16, V18.B16 + VEOR V11.B16, V7.B16, V19.B16 + VSHL $7, V16.S4, V4.S4 + VSHL $7, V17.S4, V5.S4 + VSHL $7, V18.S4, V6.S4 + VSHL $7, V19.S4, V7.S4 + VSRI $25, V16.S4, V4.S4 + VSRI $25, V17.S4, V5.S4 + VSRI $25, V18.S4, V6.S4 + VSRI $25, V19.S4, V7.S4 + + // V0..V3 += V5..V7, V4 + // V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16) + VADD V0.S4, V5.S4, V0.S4 + VADD V1.S4, V6.S4, V1.S4 + VADD V2.S4, V7.S4, V2.S4 + VADD V3.S4, V4.S4, V3.S4 + VEOR V15.B16, V0.B16, V15.B16 + VEOR V12.B16, V1.B16, V12.B16 + VEOR V13.B16, V2.B16, V13.B16 + VEOR V14.B16, V3.B16, V14.B16 + VREV32 V12.H8, V12.H8 + VREV32 V13.H8, V13.H8 + VREV32 V14.H8, V14.H8 + VREV32 V15.H8, V15.H8 + + // V10 += V15; V5 <<<= ((V10 XOR V5), 12) + // ... + VADD V15.S4, V10.S4, V10.S4 + VADD V12.S4, V11.S4, V11.S4 + VADD V13.S4, V8.S4, V8.S4 + VADD V14.S4, V9.S4, V9.S4 + VEOR V10.B16, V5.B16, V16.B16 + VEOR V11.B16, V6.B16, V17.B16 + VEOR V8.B16, V7.B16, V18.B16 + VEOR V9.B16, V4.B16, V19.B16 + VSHL $12, V16.S4, V5.S4 + VSHL $12, V17.S4, V6.S4 + VSHL $12, V18.S4, V7.S4 + VSHL $12, V19.S4, V4.S4 + VSRI $20, V16.S4, V5.S4 + VSRI $20, V17.S4, V6.S4 + VSRI $20, V18.S4, V7.S4 + VSRI $20, V19.S4, V4.S4 + + // V0 += V5; V15 <<<= ((V0 XOR V15), 8) + // ... + VADD V5.S4, V0.S4, V0.S4 + VADD V6.S4, V1.S4, V1.S4 + VADD V7.S4, V2.S4, V2.S4 + VADD V4.S4, V3.S4, V3.S4 + VEOR V0.B16, V15.B16, V15.B16 + VEOR V1.B16, V12.B16, V12.B16 + VEOR V2.B16, V13.B16, V13.B16 + VEOR V3.B16, V14.B16, V14.B16 + VTBL V31.B16, [V12.B16], V12.B16 + VTBL V31.B16, [V13.B16], V13.B16 + VTBL V31.B16, [V14.B16], V14.B16 + VTBL V31.B16, [V15.B16], V15.B16 + + // V10 += V15; V5 <<<= ((V10 XOR V5), 7) + // ... + VADD V15.S4, V10.S4, V10.S4 + VADD V12.S4, V11.S4, V11.S4 + VADD V13.S4, V8.S4, V8.S4 + VADD V14.S4, V9.S4, V9.S4 + VEOR V10.B16, V5.B16, V16.B16 + VEOR V11.B16, V6.B16, V17.B16 + VEOR V8.B16, V7.B16, V18.B16 + VEOR V9.B16, V4.B16, V19.B16 + VSHL $7, V16.S4, V5.S4 + VSHL $7, V17.S4, V6.S4 + VSHL $7, V18.S4, V7.S4 + VSHL $7, V19.S4, V4.S4 + VSRI $25, V16.S4, V5.S4 + VSRI $25, V17.S4, V6.S4 + VSRI $25, V18.S4, V7.S4 + VSRI $25, V19.S4, V4.S4 + + SUB $1, R21 + CBNZ R21, chacha + + // VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4] + WORD $0x4D60E950 + + // VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4] + WORD $0x4DFFE894 + VADD V30.S4, V12.S4, V12.S4 + VADD V16.S4, V0.S4, V0.S4 + VADD V17.S4, V1.S4, V1.S4 + VADD V18.S4, V2.S4, V2.S4 + VADD V19.S4, V3.S4, V3.S4 + // VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4] + WORD $0x4DFFE898 + // restore R4 + SUB $32, R4 + + // load counter + nonce + // VLD1R (R7), [V28.S4] + WORD $0x4D40C8FC + // VLD3R (R6), [V29.S4, V30.S4, V31.S4] + WORD $0x4D40E8DD + + VADD V20.S4, V4.S4, V4.S4 + VADD V21.S4, V5.S4, V5.S4 + VADD V22.S4, V6.S4, V6.S4 + VADD V23.S4, V7.S4, V7.S4 + VADD V24.S4, V8.S4, V8.S4 + VADD V25.S4, V9.S4, V9.S4 + VADD V26.S4, V10.S4, V10.S4 + VADD V27.S4, V11.S4, V11.S4 + VADD V28.S4, V12.S4, V12.S4 + VADD V29.S4, V13.S4, V13.S4 + VADD V30.S4, V14.S4, V14.S4 + VADD V31.S4, V15.S4, V15.S4 + + VZIP1 V1.S4, V0.S4, V16.S4 + VZIP2 V1.S4, V0.S4, V17.S4 + VZIP1 V3.S4, V2.S4, V18.S4 + VZIP2 V3.S4, V2.S4, V19.S4 + VZIP1 V5.S4, V4.S4, V20.S4 + VZIP2 V5.S4, V4.S4, V21.S4 + VZIP1 V7.S4, V6.S4, V22.S4 + VZIP2 V7.S4, V6.S4, V23.S4 + VZIP1 V9.S4, V8.S4, V24.S4 + VZIP2 V9.S4, V8.S4, V25.S4 + VZIP1 V11.S4, V10.S4, V26.S4 + VZIP2 V11.S4, V10.S4, V27.S4 + VZIP1 V13.S4, V12.S4, V28.S4 + VZIP2 V13.S4, V12.S4, V29.S4 + VZIP1 V15.S4, V14.S4, V30.S4 + VZIP2 V15.S4, V14.S4, V31.S4 + VZIP1 V18.D2, V16.D2, V0.D2 + VZIP2 V18.D2, V16.D2, V4.D2 + VZIP1 V19.D2, V17.D2, V8.D2 + VZIP2 V19.D2, V17.D2, V12.D2 + VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16] + + VZIP1 V22.D2, V20.D2, V1.D2 + VZIP2 V22.D2, V20.D2, V5.D2 + VZIP1 V23.D2, V21.D2, V9.D2 + VZIP2 V23.D2, V21.D2, V13.D2 + VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16] + VZIP1 V26.D2, V24.D2, V2.D2 + VZIP2 V26.D2, V24.D2, V6.D2 + VZIP1 V27.D2, V25.D2, V10.D2 + VZIP2 V27.D2, V25.D2, V14.D2 + VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16] + VZIP1 V30.D2, V28.D2, V3.D2 + VZIP2 V30.D2, V28.D2, V7.D2 + VZIP1 V31.D2, V29.D2, V11.D2 + VZIP2 V31.D2, V29.D2, V15.D2 + VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16] + VEOR V0.B16, V16.B16, V16.B16 + VEOR V1.B16, V17.B16, V17.B16 + VEOR V2.B16, V18.B16, V18.B16 + VEOR V3.B16, V19.B16, V19.B16 + VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1) + VEOR V4.B16, V20.B16, V20.B16 + VEOR V5.B16, V21.B16, V21.B16 + VEOR V6.B16, V22.B16, V22.B16 + VEOR V7.B16, V23.B16, V23.B16 + VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1) + VEOR V8.B16, V24.B16, V24.B16 + VEOR V9.B16, V25.B16, V25.B16 + VEOR V10.B16, V26.B16, V26.B16 + VEOR V11.B16, V27.B16, V27.B16 + VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1) + VEOR V12.B16, V28.B16, V28.B16 + VEOR V13.B16, V29.B16, V29.B16 + VEOR V14.B16, V30.B16, V30.B16 + VEOR V15.B16, V31.B16, V31.B16 + VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1) + + ADD $4, R20 + MOVW R20, (R7) // update counter + + CMP R2, R12 + BGT loop + + RET + + +DATA ·constants+0x00(SB)/4, $0x61707865 +DATA ·constants+0x04(SB)/4, $0x3320646e +DATA ·constants+0x08(SB)/4, $0x79622d32 +DATA ·constants+0x0c(SB)/4, $0x6b206574 +GLOBL ·constants(SB), NOPTR|RODATA, $32 + +DATA ·incRotMatrix+0x00(SB)/4, $0x00000000 +DATA ·incRotMatrix+0x04(SB)/4, $0x00000001 +DATA ·incRotMatrix+0x08(SB)/4, $0x00000002 +DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003 +DATA ·incRotMatrix+0x10(SB)/4, $0x02010003 +DATA ·incRotMatrix+0x14(SB)/4, $0x06050407 +DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B +DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F +GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go new file mode 100644 index 00000000..a2ecf5c3 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go @@ -0,0 +1,398 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms +// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01. +package chacha20 + +import ( + "crypto/cipher" + "encoding/binary" + "errors" + "math/bits" + + "golang.org/x/crypto/internal/subtle" +) + +const ( + // KeySize is the size of the key used by this cipher, in bytes. + KeySize = 32 + + // NonceSize is the size of the nonce used with the standard variant of this + // cipher, in bytes. + // + // Note that this is too short to be safely generated at random if the same + // key is reused more than 2³² times. + NonceSize = 12 + + // NonceSizeX is the size of the nonce used with the XChaCha20 variant of + // this cipher, in bytes. + NonceSizeX = 24 +) + +// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key +// and nonce. A *Cipher implements the cipher.Stream interface. +type Cipher struct { + // The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter + // (incremented after each block), and 3 of nonce. + key [8]uint32 + counter uint32 + nonce [3]uint32 + + // The last len bytes of buf are leftover key stream bytes from the previous + // XORKeyStream invocation. The size of buf depends on how many blocks are + // computed at a time by xorKeyStreamBlocks. + buf [bufSize]byte + len int + + // overflow is set when the counter overflowed, no more blocks can be + // generated, and the next XORKeyStream call should panic. + overflow bool + + // The counter-independent results of the first round are cached after they + // are computed the first time. + precompDone bool + p1, p5, p9, p13 uint32 + p2, p6, p10, p14 uint32 + p3, p7, p11, p15 uint32 +} + +var _ cipher.Stream = (*Cipher)(nil) + +// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given +// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided, +// the XChaCha20 construction will be used. It returns an error if key or nonce +// have any other length. +// +// Note that ChaCha20, like all stream ciphers, is not authenticated and allows +// attackers to silently tamper with the plaintext. For this reason, it is more +// appropriate as a building block than as a standalone encryption mechanism. +// Instead, consider using package golang.org/x/crypto/chacha20poly1305. +func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) { + // This function is split into a wrapper so that the Cipher allocation will + // be inlined, and depending on how the caller uses the return value, won't + // escape to the heap. + c := &Cipher{} + return newUnauthenticatedCipher(c, key, nonce) +} + +func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20: wrong key size") + } + if len(nonce) == NonceSizeX { + // XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a + // derived key, allowing it to operate on a nonce of 24 bytes. See + // draft-irtf-cfrg-xchacha-01, Section 2.3. + key, _ = HChaCha20(key, nonce[0:16]) + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + nonce = cNonce + } else if len(nonce) != NonceSize { + return nil, errors.New("chacha20: wrong nonce size") + } + + key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint + c.key = [8]uint32{ + binary.LittleEndian.Uint32(key[0:4]), + binary.LittleEndian.Uint32(key[4:8]), + binary.LittleEndian.Uint32(key[8:12]), + binary.LittleEndian.Uint32(key[12:16]), + binary.LittleEndian.Uint32(key[16:20]), + binary.LittleEndian.Uint32(key[20:24]), + binary.LittleEndian.Uint32(key[24:28]), + binary.LittleEndian.Uint32(key[28:32]), + } + c.nonce = [3]uint32{ + binary.LittleEndian.Uint32(nonce[0:4]), + binary.LittleEndian.Uint32(nonce[4:8]), + binary.LittleEndian.Uint32(nonce[8:12]), + } + return c, nil +} + +// The constant first 4 words of the ChaCha20 state. +const ( + j0 uint32 = 0x61707865 // expa + j1 uint32 = 0x3320646e // nd 3 + j2 uint32 = 0x79622d32 // 2-by + j3 uint32 = 0x6b206574 // te k +) + +const blockSize = 64 + +// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words. +// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16 +// words each round, in columnar or diagonal groups of 4 at a time. +func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { + a += b + d ^= a + d = bits.RotateLeft32(d, 16) + c += d + b ^= c + b = bits.RotateLeft32(b, 12) + a += b + d ^= a + d = bits.RotateLeft32(d, 8) + c += d + b ^= c + b = bits.RotateLeft32(b, 7) + return a, b, c, d +} + +// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will +// behave as if (64 * counter) bytes had been encrypted so far. +// +// To prevent accidental counter reuse, SetCounter panics if counter is less +// than the current value. +// +// Note that the execution time of XORKeyStream is not independent of the +// counter value. +func (s *Cipher) SetCounter(counter uint32) { + // Internally, s may buffer multiple blocks, which complicates this + // implementation slightly. When checking whether the counter has rolled + // back, we must use both s.counter and s.len to determine how many blocks + // we have already output. + outputCounter := s.counter - uint32(s.len)/blockSize + if s.overflow || counter < outputCounter { + panic("chacha20: SetCounter attempted to rollback counter") + } + + // In the general case, we set the new counter value and reset s.len to 0, + // causing the next call to XORKeyStream to refill the buffer. However, if + // we're advancing within the existing buffer, we can save work by simply + // setting s.len. + if counter < s.counter { + s.len = int(s.counter-counter) * blockSize + } else { + s.counter = counter + s.len = 0 + } +} + +// XORKeyStream XORs each byte in the given slice with a byte from the +// cipher's key stream. Dst and src must overlap entirely or not at all. +// +// If len(dst) < len(src), XORKeyStream will panic. It is acceptable +// to pass a dst bigger than src, and in that case, XORKeyStream will +// only update dst[:len(src)] and will not touch the rest of dst. +// +// Multiple calls to XORKeyStream behave as if the concatenation of +// the src buffers was passed in a single run. That is, Cipher +// maintains state and does not reset at each XORKeyStream call. +func (s *Cipher) XORKeyStream(dst, src []byte) { + if len(src) == 0 { + return + } + if len(dst) < len(src) { + panic("chacha20: output smaller than input") + } + dst = dst[:len(src)] + if subtle.InexactOverlap(dst, src) { + panic("chacha20: invalid buffer overlap") + } + + // First, drain any remaining key stream from a previous XORKeyStream. + if s.len != 0 { + keyStream := s.buf[bufSize-s.len:] + if len(src) < len(keyStream) { + keyStream = keyStream[:len(src)] + } + _ = src[len(keyStream)-1] // bounds check elimination hint + for i, b := range keyStream { + dst[i] = src[i] ^ b + } + s.len -= len(keyStream) + dst, src = dst[len(keyStream):], src[len(keyStream):] + } + if len(src) == 0 { + return + } + + // If we'd need to let the counter overflow and keep generating output, + // panic immediately. If instead we'd only reach the last block, remember + // not to generate any more output after the buffer is drained. + numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize + if s.overflow || uint64(s.counter)+numBlocks > 1<<32 { + panic("chacha20: counter overflow") + } else if uint64(s.counter)+numBlocks == 1<<32 { + s.overflow = true + } + + // xorKeyStreamBlocks implementations expect input lengths that are a + // multiple of bufSize. Platform-specific ones process multiple blocks at a + // time, so have bufSizes that are a multiple of blockSize. + + full := len(src) - len(src)%bufSize + if full > 0 { + s.xorKeyStreamBlocks(dst[:full], src[:full]) + } + dst, src = dst[full:], src[full:] + + // If using a multi-block xorKeyStreamBlocks would overflow, use the generic + // one that does one block at a time. + const blocksPerBuf = bufSize / blockSize + if uint64(s.counter)+blocksPerBuf > 1<<32 { + s.buf = [bufSize]byte{} + numBlocks := (len(src) + blockSize - 1) / blockSize + buf := s.buf[bufSize-numBlocks*blockSize:] + copy(buf, src) + s.xorKeyStreamBlocksGeneric(buf, buf) + s.len = len(buf) - copy(dst, buf) + return + } + + // If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and + // keep the leftover keystream for the next XORKeyStream invocation. + if len(src) > 0 { + s.buf = [bufSize]byte{} + copy(s.buf[:], src) + s.xorKeyStreamBlocks(s.buf[:], s.buf[:]) + s.len = bufSize - copy(dst, s.buf[:]) + } +} + +func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { + if len(dst) != len(src) || len(dst)%blockSize != 0 { + panic("chacha20: internal error: wrong dst and/or src length") + } + + // To generate each block of key stream, the initial cipher state + // (represented below) is passed through 20 rounds of shuffling, + // alternatively applying quarterRounds by columns (like 1, 5, 9, 13) + // or by diagonals (like 1, 6, 11, 12). + // + // 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc + // 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk + // 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk + // 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn + // + // c=constant k=key b=blockcount n=nonce + var ( + c0, c1, c2, c3 = j0, j1, j2, j3 + c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3] + c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7] + _, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2] + ) + + // Three quarters of the first round don't depend on the counter, so we can + // calculate them here, and reuse them for multiple blocks in the loop, and + // for future XORKeyStream invocations. + if !s.precompDone { + s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13) + s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14) + s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15) + s.precompDone = true + } + + // A condition of len(src) > 0 would be sufficient, but this also + // acts as a bounds check elimination hint. + for len(src) >= 64 && len(dst) >= 64 { + // The remainder of the first column round. + fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter) + + // The second diagonal round. + x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15) + x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12) + x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13) + x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14) + + // The remaining 18 rounds. + for i := 0; i < 9; i++ { + // Column round. + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + // Diagonal round. + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + // Add back the initial state to generate the key stream, then + // XOR the key stream with the source and write out the result. + addXor(dst[0:4], src[0:4], x0, c0) + addXor(dst[4:8], src[4:8], x1, c1) + addXor(dst[8:12], src[8:12], x2, c2) + addXor(dst[12:16], src[12:16], x3, c3) + addXor(dst[16:20], src[16:20], x4, c4) + addXor(dst[20:24], src[20:24], x5, c5) + addXor(dst[24:28], src[24:28], x6, c6) + addXor(dst[28:32], src[28:32], x7, c7) + addXor(dst[32:36], src[32:36], x8, c8) + addXor(dst[36:40], src[36:40], x9, c9) + addXor(dst[40:44], src[40:44], x10, c10) + addXor(dst[44:48], src[44:48], x11, c11) + addXor(dst[48:52], src[48:52], x12, s.counter) + addXor(dst[52:56], src[52:56], x13, c13) + addXor(dst[56:60], src[56:60], x14, c14) + addXor(dst[60:64], src[60:64], x15, c15) + + s.counter += 1 + + src, dst = src[blockSize:], dst[blockSize:] + } +} + +// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes +// key and a 16 bytes nonce. It returns an error if key or nonce have any other +// length. It is used as part of the XChaCha20 construction. +func HChaCha20(key, nonce []byte) ([]byte, error) { + // This function is split into a wrapper so that the slice allocation will + // be inlined, and depending on how the caller uses the return value, won't + // escape to the heap. + out := make([]byte, 32) + return hChaCha20(out, key, nonce) +} + +func hChaCha20(out, key, nonce []byte) ([]byte, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20: wrong HChaCha20 key size") + } + if len(nonce) != 16 { + return nil, errors.New("chacha20: wrong HChaCha20 nonce size") + } + + x0, x1, x2, x3 := j0, j1, j2, j3 + x4 := binary.LittleEndian.Uint32(key[0:4]) + x5 := binary.LittleEndian.Uint32(key[4:8]) + x6 := binary.LittleEndian.Uint32(key[8:12]) + x7 := binary.LittleEndian.Uint32(key[12:16]) + x8 := binary.LittleEndian.Uint32(key[16:20]) + x9 := binary.LittleEndian.Uint32(key[20:24]) + x10 := binary.LittleEndian.Uint32(key[24:28]) + x11 := binary.LittleEndian.Uint32(key[28:32]) + x12 := binary.LittleEndian.Uint32(nonce[0:4]) + x13 := binary.LittleEndian.Uint32(nonce[4:8]) + x14 := binary.LittleEndian.Uint32(nonce[8:12]) + x15 := binary.LittleEndian.Uint32(nonce[12:16]) + + for i := 0; i < 10; i++ { + // Diagonal round. + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + // Column round. + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + _ = out[31] // bounds check elimination hint + binary.LittleEndian.PutUint32(out[0:4], x0) + binary.LittleEndian.PutUint32(out[4:8], x1) + binary.LittleEndian.PutUint32(out[8:12], x2) + binary.LittleEndian.PutUint32(out[12:16], x3) + binary.LittleEndian.PutUint32(out[16:20], x12) + binary.LittleEndian.PutUint32(out[20:24], x13) + binary.LittleEndian.PutUint32(out[24:28], x14) + binary.LittleEndian.PutUint32(out[28:32], x15) + return out, nil +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go new file mode 100644 index 00000000..025b4989 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego +// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego + +package chacha20 + +const bufSize = blockSize + +func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) { + s.xorKeyStreamBlocksGeneric(dst, src) +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go new file mode 100644 index 00000000..da420b2e --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go @@ -0,0 +1,17 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +package chacha20 + +const bufSize = 256 + +//go:noescape +func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter) +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s new file mode 100644 index 00000000..5c0fed26 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s @@ -0,0 +1,450 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +// Code for the perl script that generates the ppc64 assembler +// can be found in the cryptogams repository at the link below. It is based on +// the original from openssl. + +// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91 + +// The differences in this and the original implementation are +// due to the calling conventions and initialization of constants. + +//go:build gc && !purego +// +build gc,!purego + +#include "textflag.h" + +#define OUT R3 +#define INP R4 +#define LEN R5 +#define KEY R6 +#define CNT R7 +#define TMP R15 + +#define CONSTBASE R16 +#define BLOCKS R17 + +DATA consts<>+0x00(SB)/8, $0x3320646e61707865 +DATA consts<>+0x08(SB)/8, $0x6b20657479622d32 +DATA consts<>+0x10(SB)/8, $0x0000000000000001 +DATA consts<>+0x18(SB)/8, $0x0000000000000000 +DATA consts<>+0x20(SB)/8, $0x0000000000000004 +DATA consts<>+0x28(SB)/8, $0x0000000000000000 +DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d +DATA consts<>+0x38(SB)/8, $0x0203000106070405 +DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c +DATA consts<>+0x48(SB)/8, $0x0102030005060704 +DATA consts<>+0x50(SB)/8, $0x6170786561707865 +DATA consts<>+0x58(SB)/8, $0x6170786561707865 +DATA consts<>+0x60(SB)/8, $0x3320646e3320646e +DATA consts<>+0x68(SB)/8, $0x3320646e3320646e +DATA consts<>+0x70(SB)/8, $0x79622d3279622d32 +DATA consts<>+0x78(SB)/8, $0x79622d3279622d32 +DATA consts<>+0x80(SB)/8, $0x6b2065746b206574 +DATA consts<>+0x88(SB)/8, $0x6b2065746b206574 +DATA consts<>+0x90(SB)/8, $0x0000000100000000 +DATA consts<>+0x98(SB)/8, $0x0000000300000002 +GLOBL consts<>(SB), RODATA, $0xa0 + +//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) +TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 + MOVD out+0(FP), OUT + MOVD inp+8(FP), INP + MOVD len+16(FP), LEN + MOVD key+24(FP), KEY + MOVD counter+32(FP), CNT + + // Addressing for constants + MOVD $consts<>+0x00(SB), CONSTBASE + MOVD $16, R8 + MOVD $32, R9 + MOVD $48, R10 + MOVD $64, R11 + SRD $6, LEN, BLOCKS + // V16 + LXVW4X (CONSTBASE)(R0), VS48 + ADD $80,CONSTBASE + + // Load key into V17,V18 + LXVW4X (KEY)(R0), VS49 + LXVW4X (KEY)(R8), VS50 + + // Load CNT, NONCE into V19 + LXVW4X (CNT)(R0), VS51 + + // Clear V27 + VXOR V27, V27, V27 + + // V28 + LXVW4X (CONSTBASE)(R11), VS60 + + // splat slot from V19 -> V26 + VSPLTW $0, V19, V26 + + VSLDOI $4, V19, V27, V19 + VSLDOI $12, V27, V19, V19 + + VADDUWM V26, V28, V26 + + MOVD $10, R14 + MOVD R14, CTR + +loop_outer_vsx: + // V0, V1, V2, V3 + LXVW4X (R0)(CONSTBASE), VS32 + LXVW4X (R8)(CONSTBASE), VS33 + LXVW4X (R9)(CONSTBASE), VS34 + LXVW4X (R10)(CONSTBASE), VS35 + + // splat values from V17, V18 into V4-V11 + VSPLTW $0, V17, V4 + VSPLTW $1, V17, V5 + VSPLTW $2, V17, V6 + VSPLTW $3, V17, V7 + VSPLTW $0, V18, V8 + VSPLTW $1, V18, V9 + VSPLTW $2, V18, V10 + VSPLTW $3, V18, V11 + + // VOR + VOR V26, V26, V12 + + // splat values from V19 -> V13, V14, V15 + VSPLTW $1, V19, V13 + VSPLTW $2, V19, V14 + VSPLTW $3, V19, V15 + + // splat const values + VSPLTISW $-16, V27 + VSPLTISW $12, V28 + VSPLTISW $8, V29 + VSPLTISW $7, V30 + +loop_vsx: + VADDUWM V0, V4, V0 + VADDUWM V1, V5, V1 + VADDUWM V2, V6, V2 + VADDUWM V3, V7, V3 + + VXOR V12, V0, V12 + VXOR V13, V1, V13 + VXOR V14, V2, V14 + VXOR V15, V3, V15 + + VRLW V12, V27, V12 + VRLW V13, V27, V13 + VRLW V14, V27, V14 + VRLW V15, V27, V15 + + VADDUWM V8, V12, V8 + VADDUWM V9, V13, V9 + VADDUWM V10, V14, V10 + VADDUWM V11, V15, V11 + + VXOR V4, V8, V4 + VXOR V5, V9, V5 + VXOR V6, V10, V6 + VXOR V7, V11, V7 + + VRLW V4, V28, V4 + VRLW V5, V28, V5 + VRLW V6, V28, V6 + VRLW V7, V28, V7 + + VADDUWM V0, V4, V0 + VADDUWM V1, V5, V1 + VADDUWM V2, V6, V2 + VADDUWM V3, V7, V3 + + VXOR V12, V0, V12 + VXOR V13, V1, V13 + VXOR V14, V2, V14 + VXOR V15, V3, V15 + + VRLW V12, V29, V12 + VRLW V13, V29, V13 + VRLW V14, V29, V14 + VRLW V15, V29, V15 + + VADDUWM V8, V12, V8 + VADDUWM V9, V13, V9 + VADDUWM V10, V14, V10 + VADDUWM V11, V15, V11 + + VXOR V4, V8, V4 + VXOR V5, V9, V5 + VXOR V6, V10, V6 + VXOR V7, V11, V7 + + VRLW V4, V30, V4 + VRLW V5, V30, V5 + VRLW V6, V30, V6 + VRLW V7, V30, V7 + + VADDUWM V0, V5, V0 + VADDUWM V1, V6, V1 + VADDUWM V2, V7, V2 + VADDUWM V3, V4, V3 + + VXOR V15, V0, V15 + VXOR V12, V1, V12 + VXOR V13, V2, V13 + VXOR V14, V3, V14 + + VRLW V15, V27, V15 + VRLW V12, V27, V12 + VRLW V13, V27, V13 + VRLW V14, V27, V14 + + VADDUWM V10, V15, V10 + VADDUWM V11, V12, V11 + VADDUWM V8, V13, V8 + VADDUWM V9, V14, V9 + + VXOR V5, V10, V5 + VXOR V6, V11, V6 + VXOR V7, V8, V7 + VXOR V4, V9, V4 + + VRLW V5, V28, V5 + VRLW V6, V28, V6 + VRLW V7, V28, V7 + VRLW V4, V28, V4 + + VADDUWM V0, V5, V0 + VADDUWM V1, V6, V1 + VADDUWM V2, V7, V2 + VADDUWM V3, V4, V3 + + VXOR V15, V0, V15 + VXOR V12, V1, V12 + VXOR V13, V2, V13 + VXOR V14, V3, V14 + + VRLW V15, V29, V15 + VRLW V12, V29, V12 + VRLW V13, V29, V13 + VRLW V14, V29, V14 + + VADDUWM V10, V15, V10 + VADDUWM V11, V12, V11 + VADDUWM V8, V13, V8 + VADDUWM V9, V14, V9 + + VXOR V5, V10, V5 + VXOR V6, V11, V6 + VXOR V7, V8, V7 + VXOR V4, V9, V4 + + VRLW V5, V30, V5 + VRLW V6, V30, V6 + VRLW V7, V30, V7 + VRLW V4, V30, V4 + BC 16, LT, loop_vsx + + VADDUWM V12, V26, V12 + + WORD $0x13600F8C // VMRGEW V0, V1, V27 + WORD $0x13821F8C // VMRGEW V2, V3, V28 + + WORD $0x10000E8C // VMRGOW V0, V1, V0 + WORD $0x10421E8C // VMRGOW V2, V3, V2 + + WORD $0x13A42F8C // VMRGEW V4, V5, V29 + WORD $0x13C63F8C // VMRGEW V6, V7, V30 + + XXPERMDI VS32, VS34, $0, VS33 + XXPERMDI VS32, VS34, $3, VS35 + XXPERMDI VS59, VS60, $0, VS32 + XXPERMDI VS59, VS60, $3, VS34 + + WORD $0x10842E8C // VMRGOW V4, V5, V4 + WORD $0x10C63E8C // VMRGOW V6, V7, V6 + + WORD $0x13684F8C // VMRGEW V8, V9, V27 + WORD $0x138A5F8C // VMRGEW V10, V11, V28 + + XXPERMDI VS36, VS38, $0, VS37 + XXPERMDI VS36, VS38, $3, VS39 + XXPERMDI VS61, VS62, $0, VS36 + XXPERMDI VS61, VS62, $3, VS38 + + WORD $0x11084E8C // VMRGOW V8, V9, V8 + WORD $0x114A5E8C // VMRGOW V10, V11, V10 + + WORD $0x13AC6F8C // VMRGEW V12, V13, V29 + WORD $0x13CE7F8C // VMRGEW V14, V15, V30 + + XXPERMDI VS40, VS42, $0, VS41 + XXPERMDI VS40, VS42, $3, VS43 + XXPERMDI VS59, VS60, $0, VS40 + XXPERMDI VS59, VS60, $3, VS42 + + WORD $0x118C6E8C // VMRGOW V12, V13, V12 + WORD $0x11CE7E8C // VMRGOW V14, V15, V14 + + VSPLTISW $4, V27 + VADDUWM V26, V27, V26 + + XXPERMDI VS44, VS46, $0, VS45 + XXPERMDI VS44, VS46, $3, VS47 + XXPERMDI VS61, VS62, $0, VS44 + XXPERMDI VS61, VS62, $3, VS46 + + VADDUWM V0, V16, V0 + VADDUWM V4, V17, V4 + VADDUWM V8, V18, V8 + VADDUWM V12, V19, V12 + + CMPU LEN, $64 + BLT tail_vsx + + // Bottom of loop + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V1, V16, V0 + VADDUWM V5, V17, V4 + VADDUWM V9, V18, V8 + VADDUWM V13, V19, V12 + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + VXOR V27, V0, V27 + + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(V10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V2, V16, V0 + VADDUWM V6, V17, V4 + VADDUWM V10, V18, V8 + VADDUWM V14, V19, V12 + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V3, V16, V0 + VADDUWM V7, V17, V4 + VADDUWM V11, V18, V8 + VADDUWM V15, V19, V12 + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + + MOVD $10, R14 + MOVD R14, CTR + BNE loop_outer_vsx + +done_vsx: + // Increment counter by number of 64 byte blocks + MOVD (CNT), R14 + ADD BLOCKS, R14 + MOVD R14, (CNT) + RET + +tail_vsx: + ADD $32, R1, R11 + MOVD LEN, CTR + + // Save values on stack to copy from + STXVW4X VS32, (R11)(R0) + STXVW4X VS36, (R11)(R8) + STXVW4X VS40, (R11)(R9) + STXVW4X VS44, (R11)(R10) + ADD $-1, R11, R12 + ADD $-1, INP + ADD $-1, OUT + +looptail_vsx: + // Copying the result to OUT + // in bytes. + MOVBZU 1(R12), KEY + MOVBZU 1(INP), TMP + XOR KEY, TMP, KEY + MOVBU KEY, 1(OUT) + BC 16, LT, looptail_vsx + + // Clear the stack values + STXVW4X VS48, (R11)(R0) + STXVW4X VS48, (R11)(R8) + STXVW4X VS48, (R11)(R9) + STXVW4X VS48, (R11)(R10) + BR done_vsx diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go new file mode 100644 index 00000000..4652247b --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go @@ -0,0 +1,28 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +package chacha20 + +import "golang.org/x/sys/cpu" + +var haveAsm = cpu.S390X.HasVX + +const bufSize = 256 + +// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only +// be called when the vector facility is available. Implementation in asm_s390x.s. +// +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + if cpu.S390X.HasVX { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) + } else { + c.xorKeyStreamBlocksGeneric(dst, src) + } +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s new file mode 100644 index 00000000..f3ef5a01 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s @@ -0,0 +1,225 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +#include "go_asm.h" +#include "textflag.h" + +// This is an implementation of the ChaCha20 encryption algorithm as +// specified in RFC 7539. It uses vector instructions to compute +// 4 keystream blocks in parallel (256 bytes) which are then XORed +// with the bytes in the input slice. + +GLOBL ·constants<>(SB), RODATA|NOPTR, $32 +// BSWAP: swap bytes in each 4-byte element +DATA ·constants<>+0x00(SB)/4, $0x03020100 +DATA ·constants<>+0x04(SB)/4, $0x07060504 +DATA ·constants<>+0x08(SB)/4, $0x0b0a0908 +DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c +// J0: [j0, j1, j2, j3] +DATA ·constants<>+0x10(SB)/4, $0x61707865 +DATA ·constants<>+0x14(SB)/4, $0x3320646e +DATA ·constants<>+0x18(SB)/4, $0x79622d32 +DATA ·constants<>+0x1c(SB)/4, $0x6b206574 + +#define BSWAP V5 +#define J0 V6 +#define KEY0 V7 +#define KEY1 V8 +#define NONCE V9 +#define CTR V10 +#define M0 V11 +#define M1 V12 +#define M2 V13 +#define M3 V14 +#define INC V15 +#define X0 V16 +#define X1 V17 +#define X2 V18 +#define X3 V19 +#define X4 V20 +#define X5 V21 +#define X6 V22 +#define X7 V23 +#define X8 V24 +#define X9 V25 +#define X10 V26 +#define X11 V27 +#define X12 V28 +#define X13 V29 +#define X14 V30 +#define X15 V31 + +#define NUM_ROUNDS 20 + +#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $16, a2, a2 \ + VERLLF $16, b2, b2 \ + VERLLF $16, c2, c2 \ + VERLLF $16, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $12, a1, a1 \ + VERLLF $12, b1, b1 \ + VERLLF $12, c1, c1 \ + VERLLF $12, d1, d1 \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $8, a2, a2 \ + VERLLF $8, b2, b2 \ + VERLLF $8, c2, c2 \ + VERLLF $8, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $7, a1, a1 \ + VERLLF $7, b1, b1 \ + VERLLF $7, c1, c1 \ + VERLLF $7, d1, d1 + +#define PERMUTE(mask, v0, v1, v2, v3) \ + VPERM v0, v0, mask, v0 \ + VPERM v1, v1, mask, v1 \ + VPERM v2, v2, mask, v2 \ + VPERM v3, v3, mask, v3 + +#define ADDV(x, v0, v1, v2, v3) \ + VAF x, v0, v0 \ + VAF x, v1, v1 \ + VAF x, v2, v2 \ + VAF x, v3, v3 + +#define XORV(off, dst, src, v0, v1, v2, v3) \ + VLM off(src), M0, M3 \ + PERMUTE(BSWAP, v0, v1, v2, v3) \ + VX v0, M0, M0 \ + VX v1, M1, M1 \ + VX v2, M2, M2 \ + VX v3, M3, M3 \ + VSTM M0, M3, off(dst) + +#define SHUFFLE(a, b, c, d, t, u, v, w) \ + VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]} + VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]} + VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]} + VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]} + VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]} + VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]} + VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} + VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} + +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) +TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 + MOVD $·constants<>(SB), R1 + MOVD dst+0(FP), R2 // R2=&dst[0] + LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src) + MOVD key+48(FP), R5 // R5=key + MOVD nonce+56(FP), R6 // R6=nonce + MOVD counter+64(FP), R7 // R7=counter + + // load BSWAP and J0 + VLM (R1), BSWAP, J0 + + // setup + MOVD $95, R0 + VLM (R5), KEY0, KEY1 + VLL R0, (R6), NONCE + VZERO M0 + VLEIB $7, $32, M0 + VSRLB M0, NONCE, NONCE + + // initialize counter values + VLREPF (R7), CTR + VZERO INC + VLEIF $1, $1, INC + VLEIF $2, $2, INC + VLEIF $3, $3, INC + VAF INC, CTR, CTR + VREPIF $4, INC + +chacha: + VREPF $0, J0, X0 + VREPF $1, J0, X1 + VREPF $2, J0, X2 + VREPF $3, J0, X3 + VREPF $0, KEY0, X4 + VREPF $1, KEY0, X5 + VREPF $2, KEY0, X6 + VREPF $3, KEY0, X7 + VREPF $0, KEY1, X8 + VREPF $1, KEY1, X9 + VREPF $2, KEY1, X10 + VREPF $3, KEY1, X11 + VLR CTR, X12 + VREPF $1, NONCE, X13 + VREPF $2, NONCE, X14 + VREPF $3, NONCE, X15 + + MOVD $(NUM_ROUNDS/2), R1 + +loop: + ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11) + ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9) + + ADD $-1, R1 + BNE loop + + // decrement length + ADD $-256, R4 + + // rearrange vectors + SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) + ADDV(J0, X0, X1, X2, X3) + SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3) + ADDV(KEY0, X4, X5, X6, X7) + SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3) + ADDV(KEY1, X8, X9, X10, X11) + VAF CTR, X12, X12 + SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3) + ADDV(NONCE, X12, X13, X14, X15) + + // increment counters + VAF INC, CTR, CTR + + // xor keystream with plaintext + XORV(0*64, R2, R3, X0, X4, X8, X12) + XORV(1*64, R2, R3, X1, X5, X9, X13) + XORV(2*64, R2, R3, X2, X6, X10, X14) + XORV(3*64, R2, R3, X3, X7, X11, X15) + + // increment pointers + MOVD $256(R2), R2 + MOVD $256(R3), R3 + + CMPBNE R4, $0, chacha + + VSTEF $0, CTR, (R7) + RET diff --git a/vendor/golang.org/x/crypto/chacha20/xor.go b/vendor/golang.org/x/crypto/chacha20/xor.go new file mode 100644 index 00000000..c2d04851 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/xor.go @@ -0,0 +1,42 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found src the LICENSE file. + +package chacha20 + +import "runtime" + +// Platforms that have fast unaligned 32-bit little endian accesses. +const unaligned = runtime.GOARCH == "386" || + runtime.GOARCH == "amd64" || + runtime.GOARCH == "arm64" || + runtime.GOARCH == "ppc64le" || + runtime.GOARCH == "s390x" + +// addXor reads a little endian uint32 from src, XORs it with (a + b) and +// places the result in little endian byte order in dst. +func addXor(dst, src []byte, a, b uint32) { + _, _ = src[3], dst[3] // bounds check elimination hint + if unaligned { + // The compiler should optimize this code into + // 32-bit unaligned little endian loads and stores. + // TODO: delete once the compiler does a reliably + // good job with the generic code below. + // See issue #25111 for more details. + v := uint32(src[0]) + v |= uint32(src[1]) << 8 + v |= uint32(src[2]) << 16 + v |= uint32(src[3]) << 24 + v ^= a + b + dst[0] = byte(v) + dst[1] = byte(v >> 8) + dst[2] = byte(v >> 16) + dst[3] = byte(v >> 24) + } else { + a += b + dst[0] = src[0] ^ byte(a) + dst[1] = src[1] ^ byte(a>>8) + dst[2] = src[2] ^ byte(a>>16) + dst[3] = src[3] ^ byte(a>>24) + } +} diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go new file mode 100644 index 00000000..bc62161d --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -0,0 +1,146 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package curve25519 provides an implementation of the X25519 function, which +// performs scalar multiplication on the elliptic curve known as Curve25519. +// See RFC 7748. +package curve25519 // import "golang.org/x/crypto/curve25519" + +import ( + "crypto/subtle" + "errors" + "strconv" + + "golang.org/x/crypto/curve25519/internal/field" +) + +// ScalarMult sets dst to the product scalar * point. +// +// Deprecated: when provided a low-order point, ScalarMult will set dst to all +// zeroes, irrespective of the scalar. Instead, use the X25519 function, which +// will return an error. +func ScalarMult(dst, scalar, point *[32]byte) { + var e [32]byte + + copy(e[:], scalar[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element + x1.SetBytes(point[:]) + x2.One() + x3.Set(&x1) + z3.One() + + swap := 0 + for pos := 254; pos >= 0; pos-- { + b := e[pos/8] >> uint(pos&7) + b &= 1 + swap ^= int(b) + x2.Swap(&x3, swap) + z2.Swap(&z3, swap) + swap = int(b) + + tmp0.Subtract(&x3, &z3) + tmp1.Subtract(&x2, &z2) + x2.Add(&x2, &z2) + z2.Add(&x3, &z3) + z3.Multiply(&tmp0, &x2) + z2.Multiply(&z2, &tmp1) + tmp0.Square(&tmp1) + tmp1.Square(&x2) + x3.Add(&z3, &z2) + z2.Subtract(&z3, &z2) + x2.Multiply(&tmp1, &tmp0) + tmp1.Subtract(&tmp1, &tmp0) + z2.Square(&z2) + + z3.Mult32(&tmp1, 121666) + x3.Square(&x3) + tmp0.Add(&tmp0, &z3) + z3.Multiply(&x1, &z2) + z2.Multiply(&tmp1, &tmp0) + } + + x2.Swap(&x3, swap) + z2.Swap(&z3, swap) + + z2.Invert(&z2) + x2.Multiply(&x2, &z2) + copy(dst[:], x2.Bytes()) +} + +// ScalarBaseMult sets dst to the product scalar * base where base is the +// standard generator. +// +// It is recommended to use the X25519 function with Basepoint instead, as +// copying into fixed size arrays can lead to unexpected bugs. +func ScalarBaseMult(dst, scalar *[32]byte) { + ScalarMult(dst, scalar, &basePoint) +} + +const ( + // ScalarSize is the size of the scalar input to X25519. + ScalarSize = 32 + // PointSize is the size of the point input to X25519. + PointSize = 32 +) + +// Basepoint is the canonical Curve25519 generator. +var Basepoint []byte + +var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +func init() { Basepoint = basePoint[:] } + +func checkBasepoint() { + if subtle.ConstantTimeCompare(Basepoint, []byte{ + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }) != 1 { + panic("curve25519: global Basepoint value was modified") + } +} + +// X25519 returns the result of the scalar multiplication (scalar * point), +// according to RFC 7748, Section 5. scalar, point and the return value are +// slices of 32 bytes. +// +// scalar can be generated at random, for example with crypto/rand. point should +// be either Basepoint or the output of another X25519 call. +// +// If point is Basepoint (but not if it's a different slice with the same +// contents) a precomputed implementation might be used for performance. +func X25519(scalar, point []byte) ([]byte, error) { + // Outline the body of function, to let the allocation be inlined in the + // caller, and possibly avoid escaping to the heap. + var dst [32]byte + return x25519(&dst, scalar, point) +} + +func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { + var in [32]byte + if l := len(scalar); l != 32 { + return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32") + } + if l := len(point); l != 32 { + return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32") + } + copy(in[:], scalar) + if &point[0] == &Basepoint[0] { + checkBasepoint() + ScalarBaseMult(dst, &in) + } else { + var base, zero [32]byte + copy(base[:], point) + ScalarMult(dst, &in, &base) + if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 { + return nil, errors.New("bad input point: low order point") + } + } + return dst[:], nil +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/README b/vendor/golang.org/x/crypto/curve25519/internal/field/README new file mode 100644 index 00000000..e25bca7d --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/README @@ -0,0 +1,7 @@ +This package is kept in sync with crypto/ed25519/internal/edwards25519/field in +the standard library. + +If there are any changes in the standard library that need to be synced to this +package, run sync.sh. It will not overwrite any local changes made since the +previous sync, so it's ok to land changes in this package first, and then sync +to the standard library later. diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go new file mode 100644 index 00000000..ca841ad9 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go @@ -0,0 +1,416 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package field implements fast arithmetic modulo 2^255-19. +package field + +import ( + "crypto/subtle" + "encoding/binary" + "math/bits" +) + +// Element represents an element of the field GF(2^255-19). Note that this +// is not a cryptographically secure group, and should only be used to interact +// with edwards25519.Point coordinates. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is a valid zero element. +type Element struct { + // An element t represents the integer + // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 + // + // Between operations, all limbs are expected to be lower than 2^52. + l0 uint64 + l1 uint64 + l2 uint64 + l3 uint64 + l4 uint64 +} + +const maskLow51Bits uint64 = (1 << 51) - 1 + +var feZero = &Element{0, 0, 0, 0, 0} + +// Zero sets v = 0, and returns v. +func (v *Element) Zero() *Element { + *v = *feZero + return v +} + +var feOne = &Element{1, 0, 0, 0, 0} + +// One sets v = 1, and returns v. +func (v *Element) One() *Element { + *v = *feOne + return v +} + +// reduce reduces v modulo 2^255 - 19 and returns it. +func (v *Element) reduce() *Element { + v.carryPropagate() + + // After the light reduction we now have a field element representation + // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. + + // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, + // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. + c := (v.l0 + 19) >> 51 + c = (v.l1 + c) >> 51 + c = (v.l2 + c) >> 51 + c = (v.l3 + c) >> 51 + c = (v.l4 + c) >> 51 + + // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's + // effectively applying the reduction identity to the carry. + v.l0 += 19 * c + + v.l1 += v.l0 >> 51 + v.l0 = v.l0 & maskLow51Bits + v.l2 += v.l1 >> 51 + v.l1 = v.l1 & maskLow51Bits + v.l3 += v.l2 >> 51 + v.l2 = v.l2 & maskLow51Bits + v.l4 += v.l3 >> 51 + v.l3 = v.l3 & maskLow51Bits + // no additional carry + v.l4 = v.l4 & maskLow51Bits + + return v +} + +// Add sets v = a + b, and returns v. +func (v *Element) Add(a, b *Element) *Element { + v.l0 = a.l0 + b.l0 + v.l1 = a.l1 + b.l1 + v.l2 = a.l2 + b.l2 + v.l3 = a.l3 + b.l3 + v.l4 = a.l4 + b.l4 + // Using the generic implementation here is actually faster than the + // assembly. Probably because the body of this function is so simple that + // the compiler can figure out better optimizations by inlining the carry + // propagation. TODO + return v.carryPropagateGeneric() +} + +// Subtract sets v = a - b, and returns v. +func (v *Element) Subtract(a, b *Element) *Element { + // We first add 2 * p, to guarantee the subtraction won't underflow, and + // then subtract b (which can be up to 2^255 + 2^13 * 19). + v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 + v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 + v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 + v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 + v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + return v.carryPropagate() +} + +// Negate sets v = -a, and returns v. +func (v *Element) Negate(a *Element) *Element { + return v.Subtract(feZero, a) +} + +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + t.Square(&z2) // 4 + t.Square(&t) // 8 + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +} + +// Set sets v = a, and returns v. +func (v *Element) Set(a *Element) *Element { + *v = *a + return v +} + +// SetBytes sets v to x, which must be a 32-byte little-endian encoding. +// +// Consistent with RFC 7748, the most significant bit (the high bit of the +// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) +// are accepted. Note that this is laxer than specified by RFC 8032. +func (v *Element) SetBytes(x []byte) *Element { + if len(x) != 32 { + panic("edwards25519: invalid field element input size") + } + + // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). + v.l0 = binary.LittleEndian.Uint64(x[0:8]) + v.l0 &= maskLow51Bits + // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). + v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 + v.l1 &= maskLow51Bits + // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). + v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 + v.l2 &= maskLow51Bits + // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). + v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 + v.l3 &= maskLow51Bits + // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). + // Note: not bytes 25:33, shift 4, to avoid overread. + v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 + v.l4 &= maskLow51Bits + + return v +} + +// Bytes returns the canonical 32-byte little-endian encoding of v. +func (v *Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [32]byte + return v.bytes(&out) +} + +func (v *Element) bytes(out *[32]byte) []byte { + t := *v + t.reduce() + + var buf [8]byte + for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { + bitsOffset := i * 51 + binary.LittleEndian.PutUint64(buf[:], l<= len(out) { + break + } + out[off] |= bb + } + } + + return out[:] +} + +// Equal returns 1 if v and u are equal, and 0 otherwise. +func (v *Element) Equal(u *Element) int { + sa, sv := u.Bytes(), v.Bytes() + return subtle.ConstantTimeCompare(sa, sv) +} + +// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. +func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *Element) Select(a, b *Element, cond int) *Element { + m := mask64Bits(cond) + v.l0 = (m & a.l0) | (^m & b.l0) + v.l1 = (m & a.l1) | (^m & b.l1) + v.l2 = (m & a.l2) | (^m & b.l2) + v.l3 = (m & a.l3) | (^m & b.l3) + v.l4 = (m & a.l4) | (^m & b.l4) + return v +} + +// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. +func (v *Element) Swap(u *Element, cond int) { + m := mask64Bits(cond) + t := m & (v.l0 ^ u.l0) + v.l0 ^= t + u.l0 ^= t + t = m & (v.l1 ^ u.l1) + v.l1 ^= t + u.l1 ^= t + t = m & (v.l2 ^ u.l2) + v.l2 ^= t + u.l2 ^= t + t = m & (v.l3 ^ u.l3) + v.l3 ^= t + u.l3 ^= t + t = m & (v.l4 ^ u.l4) + v.l4 ^= t + u.l4 ^= t +} + +// IsNegative returns 1 if v is negative, and 0 otherwise. +func (v *Element) IsNegative() int { + return int(v.Bytes()[0] & 1) +} + +// Absolute sets v to |u|, and returns v. +func (v *Element) Absolute(u *Element) *Element { + return v.Select(new(Element).Negate(u), u, u.IsNegative()) +} + +// Multiply sets v = x * y, and returns v. +func (v *Element) Multiply(x, y *Element) *Element { + feMul(v, x, y) + return v +} + +// Square sets v = x * x, and returns v. +func (v *Element) Square(x *Element) *Element { + feSquare(v, x) + return v +} + +// Mult32 sets v = x * y, and returns v. +func (v *Element) Mult32(x *Element, y uint32) *Element { + x0lo, x0hi := mul51(x.l0, y) + x1lo, x1hi := mul51(x.l1, y) + x2lo, x2hi := mul51(x.l2, y) + x3lo, x3hi := mul51(x.l3, y) + x4lo, x4hi := mul51(x.l4, y) + v.l0 = x0lo + 19*x4hi // carried over per the reduction identity + v.l1 = x1lo + x0hi + v.l2 = x2lo + x1hi + v.l3 = x3lo + x2hi + v.l4 = x4lo + x3hi + // The hi portions are going to be only 32 bits, plus any previous excess, + // so we can skip the carry propagation. + return v +} + +// mul51 returns lo + hi * 2⁵¹ = a * b. +func mul51(a uint64, b uint32) (lo uint64, hi uint64) { + mh, ml := bits.Mul64(a, uint64(b)) + lo = ml & maskLow51Bits + hi = (mh << 13) | (ml >> 51) + return +} + +// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. +func (v *Element) Pow22523(x *Element) *Element { + var t0, t1, t2 Element + + t0.Square(x) // x^2 + t1.Square(&t0) // x^4 + t1.Square(&t1) // x^8 + t1.Multiply(x, &t1) // x^9 + t0.Multiply(&t0, &t1) // x^11 + t0.Square(&t0) // x^22 + t0.Multiply(&t1, &t0) // x^31 + t1.Square(&t0) // x^62 + for i := 1; i < 5; i++ { // x^992 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 + t1.Square(&t0) // 2^11 - 2 + for i := 1; i < 10; i++ { // 2^20 - 2^10 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^20 - 1 + t2.Square(&t1) // 2^21 - 2 + for i := 1; i < 20; i++ { // 2^40 - 2^20 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^40 - 1 + t1.Square(&t1) // 2^41 - 2 + for i := 1; i < 10; i++ { // 2^50 - 2^10 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^50 - 1 + t1.Square(&t0) // 2^51 - 2 + for i := 1; i < 50; i++ { // 2^100 - 2^50 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^100 - 1 + t2.Square(&t1) // 2^101 - 2 + for i := 1; i < 100; i++ { // 2^200 - 2^100 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^200 - 1 + t1.Square(&t1) // 2^201 - 2 + for i := 1; i < 50; i++ { // 2^250 - 2^50 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^250 - 1 + t0.Square(&t0) // 2^251 - 2 + t0.Square(&t0) // 2^252 - 4 + return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) +} + +// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. +var sqrtM1 = &Element{1718705420411056, 234908883556509, + 2233514472574048, 2117202627021982, 765476049583133} + +// SqrtRatio sets r to the non-negative square root of the ratio of u and v. +// +// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio +// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, +// and returns r and 0. +func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { + var a, b Element + + // r = (u * v3) * (u * v7)^((p-5)/8) + v2 := a.Square(v) + uv3 := b.Multiply(u, b.Multiply(v2, v)) + uv7 := a.Multiply(uv3, a.Square(v2)) + r.Multiply(uv3, r.Pow22523(uv7)) + + check := a.Multiply(v, a.Square(r)) // check = v * r^2 + + uNeg := b.Negate(u) + correctSignSqrt := check.Equal(u) + flippedSignSqrt := check.Equal(uNeg) + flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) + + rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r + // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) + r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) + + r.Absolute(r) // Choose the nonnegative square root. + return r, correctSignSqrt | flippedSignSqrt +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go new file mode 100644 index 00000000..edcf163c --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go @@ -0,0 +1,16 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build amd64 && gc && !purego +// +build amd64,gc,!purego + +package field + +// feMul sets out = a * b. It works like feMulGeneric. +// +//go:noescape +func feMul(out *Element, a *Element, b *Element) + +// feSquare sets out = a * a. It works like feSquareGeneric. +// +//go:noescape +func feSquare(out *Element, a *Element) diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s new file mode 100644 index 00000000..293f013c --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s @@ -0,0 +1,379 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build amd64 && gc && !purego +// +build amd64,gc,!purego + +#include "textflag.h" + +// func feMul(out *Element, a *Element, b *Element) +TEXT ·feMul(SB), NOSPLIT, $0-24 + MOVQ a+8(FP), CX + MOVQ b+16(FP), BX + + // r0 = a0×b0 + MOVQ (CX), AX + MULQ (BX) + MOVQ AX, DI + MOVQ DX, SI + + // r0 += 19×a1×b4 + MOVQ 8(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a2×b3 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a3×b2 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a4×b1 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 8(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r1 = a0×b1 + MOVQ (CX), AX + MULQ 8(BX) + MOVQ AX, R9 + MOVQ DX, R8 + + // r1 += a1×b0 + MOVQ 8(CX), AX + MULQ (BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a2×b4 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a3×b3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a4×b2 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r2 = a0×b2 + MOVQ (CX), AX + MULQ 16(BX) + MOVQ AX, R11 + MOVQ DX, R10 + + // r2 += a1×b1 + MOVQ 8(CX), AX + MULQ 8(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += a2×b0 + MOVQ 16(CX), AX + MULQ (BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a3×b4 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a4×b3 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r3 = a0×b3 + MOVQ (CX), AX + MULQ 24(BX) + MOVQ AX, R13 + MOVQ DX, R12 + + // r3 += a1×b2 + MOVQ 8(CX), AX + MULQ 16(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a2×b1 + MOVQ 16(CX), AX + MULQ 8(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a3×b0 + MOVQ 24(CX), AX + MULQ (BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += 19×a4×b4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r4 = a0×b4 + MOVQ (CX), AX + MULQ 32(BX) + MOVQ AX, R15 + MOVQ DX, R14 + + // r4 += a1×b3 + MOVQ 8(CX), AX + MULQ 24(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a2×b2 + MOVQ 16(CX), AX + MULQ 16(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a3×b1 + MOVQ 24(CX), AX + MULQ 8(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a4×b0 + MOVQ 32(CX), AX + MULQ (BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, DI, SI + SHLQ $0x0d, R9, R8 + SHLQ $0x0d, R11, R10 + SHLQ $0x0d, R13, R12 + SHLQ $0x0d, R15, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Second reduction chain (carryPropagate) + MOVQ DI, SI + SHRQ $0x33, SI + MOVQ R9, R8 + SHRQ $0x33, R8 + MOVQ R11, R10 + SHRQ $0x33, R10 + MOVQ R13, R12 + SHRQ $0x33, R12 + MOVQ R15, R14 + SHRQ $0x33, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Store output + MOVQ out+0(FP), AX + MOVQ DI, (AX) + MOVQ R9, 8(AX) + MOVQ R11, 16(AX) + MOVQ R13, 24(AX) + MOVQ R15, 32(AX) + RET + +// func feSquare(out *Element, a *Element) +TEXT ·feSquare(SB), NOSPLIT, $0-16 + MOVQ a+8(FP), CX + + // r0 = l0×l0 + MOVQ (CX), AX + MULQ (CX) + MOVQ AX, SI + MOVQ DX, BX + + // r0 += 38×l1×l4 + MOVQ 8(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r0 += 38×l2×l3 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 24(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r1 = 2×l0×l1 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 8(CX) + MOVQ AX, R8 + MOVQ DX, DI + + // r1 += 38×l2×l4 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r1 += 19×l3×l3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r2 = 2×l0×l2 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 16(CX) + MOVQ AX, R10 + MOVQ DX, R9 + + // r2 += l1×l1 + MOVQ 8(CX), AX + MULQ 8(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r2 += 38×l3×l4 + MOVQ 24(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r3 = 2×l0×l3 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 24(CX) + MOVQ AX, R12 + MOVQ DX, R11 + + // r3 += 2×l1×l2 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 16(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r3 += 19×l4×l4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r4 = 2×l0×l4 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 32(CX) + MOVQ AX, R14 + MOVQ DX, R13 + + // r4 += 2×l1×l3 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 24(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // r4 += l2×l2 + MOVQ 16(CX), AX + MULQ 16(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, SI, BX + SHLQ $0x0d, R8, DI + SHLQ $0x0d, R10, R9 + SHLQ $0x0d, R12, R11 + SHLQ $0x0d, R14, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Second reduction chain (carryPropagate) + MOVQ SI, BX + SHRQ $0x33, BX + MOVQ R8, DI + SHRQ $0x33, DI + MOVQ R10, R9 + SHRQ $0x33, R9 + MOVQ R12, R11 + SHRQ $0x33, R11 + MOVQ R14, R13 + SHRQ $0x33, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Store output + MOVQ out+0(FP), AX + MOVQ SI, (AX) + MOVQ R8, 8(AX) + MOVQ R10, 16(AX) + MOVQ R12, 24(AX) + MOVQ R14, 32(AX) + RET diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go new file mode 100644 index 00000000..ddb6c9b8 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || !gc || purego +// +build !amd64 !gc purego + +package field + +func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } + +func feSquare(v, x *Element) { feSquareGeneric(v, x) } diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go new file mode 100644 index 00000000..af459ef5 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go @@ -0,0 +1,16 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm64 && gc && !purego +// +build arm64,gc,!purego + +package field + +//go:noescape +func carryPropagate(v *Element) + +func (v *Element) carryPropagate() *Element { + carryPropagate(v) + return v +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s new file mode 100644 index 00000000..5c91e458 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s @@ -0,0 +1,43 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm64 && gc && !purego +// +build arm64,gc,!purego + +#include "textflag.h" + +// carryPropagate works exactly like carryPropagateGeneric and uses the +// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but +// avoids loading R0-R4 twice and uses LDP and STP. +// +// See https://golang.org/issues/43145 for the main compiler issue. +// +// func carryPropagate(v *Element) +TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 + MOVD v+0(FP), R20 + + LDP 0(R20), (R0, R1) + LDP 16(R20), (R2, R3) + MOVD 32(R20), R4 + + AND $0x7ffffffffffff, R0, R10 + AND $0x7ffffffffffff, R1, R11 + AND $0x7ffffffffffff, R2, R12 + AND $0x7ffffffffffff, R3, R13 + AND $0x7ffffffffffff, R4, R14 + + ADD R0>>51, R11, R11 + ADD R1>>51, R12, R12 + ADD R2>>51, R13, R13 + ADD R3>>51, R14, R14 + // R4>>51 * 19 + R10 -> R10 + LSR $51, R4, R21 + MOVD $19, R22 + MADD R22, R10, R21, R10 + + STP (R10, R11), 0(R20) + STP (R12, R13), 16(R20) + MOVD R14, 32(R20) + + RET diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go new file mode 100644 index 00000000..234a5b2e --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !arm64 || !gc || purego +// +build !arm64 !gc purego + +package field + +func (v *Element) carryPropagate() *Element { + return v.carryPropagateGeneric() +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go new file mode 100644 index 00000000..7b5b78cb --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go @@ -0,0 +1,264 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "math/bits" + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +// mul64 returns a * b. +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +// addMul64 returns v + a * b. +func addMul64(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + +// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. +func shiftRightBy51(a uint128) uint64 { + return (a.hi << (64 - 51)) | (a.lo >> 51) +} + +func feMulGeneric(v, a, b *Element) { + a0 := a.l0 + a1 := a.l1 + a2 := a.l2 + a3 := a.l3 + a4 := a.l4 + + b0 := b.l0 + b1 := b.l1 + b2 := b.l2 + b3 := b.l3 + b4 := b.l4 + + // Limb multiplication works like pen-and-paper columnar multiplication, but + // with 51-bit limbs instead of digits. + // + // a4 a3 a2 a1 a0 x + // b4 b3 b2 b1 b0 = + // ------------------------ + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a4b1 a3b1 a2b1 a1b1 a0b1 + + // a4b2 a3b2 a2b2 a1b2 a0b2 + + // a4b3 a3b3 a2b3 a1b3 a0b3 + + // a4b4 a3b4 a2b4 a1b4 a0b4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to + // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, + // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. + // + // Reduction can be carried out simultaneously to multiplication. For + // example, we do not compute r5: whenever the result of a multiplication + // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. + // + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a3b1 a2b1 a1b1 a0b1 19×a4b1 + + // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + + // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + + // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // Finally we add up the columns into wide, overlapping limbs. + + a1_19 := a1 * 19 + a2_19 := a2 * 19 + a3_19 := a3 * 19 + a4_19 := a4 * 19 + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := mul64(a0, b0) + r0 = addMul64(r0, a1_19, b4) + r0 = addMul64(r0, a2_19, b3) + r0 = addMul64(r0, a3_19, b2) + r0 = addMul64(r0, a4_19, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := mul64(a0, b1) + r1 = addMul64(r1, a1, b0) + r1 = addMul64(r1, a2_19, b4) + r1 = addMul64(r1, a3_19, b3) + r1 = addMul64(r1, a4_19, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := mul64(a0, b2) + r2 = addMul64(r2, a1, b1) + r2 = addMul64(r2, a2, b0) + r2 = addMul64(r2, a3_19, b4) + r2 = addMul64(r2, a4_19, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := mul64(a0, b3) + r3 = addMul64(r3, a1, b2) + r3 = addMul64(r3, a2, b1) + r3 = addMul64(r3, a3, b0) + r3 = addMul64(r3, a4_19, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := mul64(a0, b4) + r4 = addMul64(r4, a1, b3) + r4 = addMul64(r4, a2, b2) + r4 = addMul64(r4, a3, b1) + r4 = addMul64(r4, a4, b0) + + // After the multiplication, we need to reduce (carry) the five coefficients + // to obtain a result with limbs that are at most slightly larger than 2⁵¹, + // to respect the Element invariant. + // + // Overall, the reduction works the same as carryPropagate, except with + // wider inputs: we take the carry for each coefficient by shifting it right + // by 51, and add it to the limb above it. The top carry is multiplied by 19 + // according to the reduction identity and added to the lowest limb. + // + // The largest coefficient (r0) will be at most 111 bits, which guarantees + // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. + // + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) + // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² + // r0 < 2⁷ × 2⁵² × 2⁵² + // r0 < 2¹¹¹ + // + // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most + // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and + // allows us to easily apply the reduction identity. + // + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + // r4 < 5 × 2⁵² × 2⁵² + // r4 < 2¹⁰⁷ + // + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + // Now all coefficients fit into 64-bit registers but are still too large to + // be passed around as a Element. We therefore do one last carry chain, + // where the carries will be small enough to fit in the wiggle room above 2⁵¹. + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +func feSquareGeneric(v, a *Element) { + l0 := a.l0 + l1 := a.l1 + l2 := a.l2 + l3 := a.l3 + l4 := a.l4 + + // Squaring works precisely like multiplication above, but thanks to its + // symmetry we get to group a few terms together. + // + // l4 l3 l2 l1 l0 x + // l4 l3 l2 l1 l0 = + // ------------------------ + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l4l1 l3l1 l2l1 l1l1 l0l1 + + // l4l2 l3l2 l2l2 l1l2 l0l2 + + // l4l3 l3l3 l2l3 l1l3 l0l3 + + // l4l4 l3l4 l2l4 l1l4 l0l4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l3l1 l2l1 l1l1 l0l1 19×l4l1 + + // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + + // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + + // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with + // only three Mul64 and four Add64, instead of five and eight. + + l0_2 := l0 * 2 + l1_2 := l1 * 2 + + l1_38 := l1 * 38 + l2_38 := l2 * 38 + l3_38 := l3 * 38 + + l3_19 := l3 * 19 + l4_19 := l4 * 19 + + // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := mul64(l0, l0) + r0 = addMul64(r0, l1_38, l4) + r0 = addMul64(r0, l2_38, l3) + + // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := mul64(l0_2, l1) + r1 = addMul64(r1, l2_38, l4) + r1 = addMul64(r1, l3_19, l3) + + // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := mul64(l0_2, l2) + r2 = addMul64(r2, l1, l1) + r2 = addMul64(r2, l3_38, l4) + + // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := mul64(l0_2, l3) + r3 = addMul64(r3, l1_2, l2) + r3 = addMul64(r3, l4_19, l4) + + // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := mul64(l0_2, l4) + r4 = addMul64(r4, l1_2, l3) + r4 = addMul64(r4, l2, l2) + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +// carryPropagate brings the limbs below 52 bits by applying the reduction +// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline +func (v *Element) carryPropagateGeneric() *Element { + c0 := v.l0 >> 51 + c1 := v.l1 >> 51 + c2 := v.l2 >> 51 + c3 := v.l3 >> 51 + c4 := v.l4 >> 51 + + v.l0 = v.l0&maskLow51Bits + c4*19 + v.l1 = v.l1&maskLow51Bits + c0 + v.l2 = v.l2&maskLow51Bits + c1 + v.l3 = v.l3&maskLow51Bits + c2 + v.l4 = v.l4&maskLow51Bits + c3 + + return v +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint new file mode 100644 index 00000000..e3685f95 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint @@ -0,0 +1 @@ +b0c49ae9f59d233526f8934262c5bbbe14d4358d diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh new file mode 100644 index 00000000..1ba22a8b --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh @@ -0,0 +1,19 @@ +#! /bin/bash +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +STD_PATH=src/crypto/ed25519/internal/edwards25519/field +LOCAL_PATH=curve25519/internal/field +LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint) + +git fetch https://go.googlesource.com/go master + +if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then + echo "No changes." +else + NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint) + echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..." + git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \ + git apply -3 --directory=$LOCAL_PATH +fi diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go new file mode 100644 index 00000000..a7828345 --- /dev/null +++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go @@ -0,0 +1,71 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ed25519 implements the Ed25519 signature algorithm. See +// https://ed25519.cr.yp.to/. +// +// These functions are also compatible with the “Ed25519” function defined in +// RFC 8032. However, unlike RFC 8032's formulation, this package's private key +// representation includes a public key suffix to make multiple signing +// operations with the same key more efficient. This package refers to the RFC +// 8032 private key as the “seed”. +// +// Beginning with Go 1.13, the functionality of this package was moved to the +// standard library as crypto/ed25519. This package only acts as a compatibility +// wrapper. +package ed25519 + +import ( + "crypto/ed25519" + "io" +) + +const ( + // PublicKeySize is the size, in bytes, of public keys as used in this package. + PublicKeySize = 32 + // PrivateKeySize is the size, in bytes, of private keys as used in this package. + PrivateKeySize = 64 + // SignatureSize is the size, in bytes, of signatures generated and verified by this package. + SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 32 +) + +// PublicKey is the type of Ed25519 public keys. +// +// This type is an alias for crypto/ed25519's PublicKey type. +// See the crypto/ed25519 package for the methods on this type. +type PublicKey = ed25519.PublicKey + +// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. +// +// This type is an alias for crypto/ed25519's PrivateKey type. +// See the crypto/ed25519 package for the methods on this type. +type PrivateKey = ed25519.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + return ed25519.GenerateKey(rand) +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + return ed25519.NewKeyFromSeed(seed) +} + +// Sign signs the message with privateKey and returns a signature. It will +// panic if len(privateKey) is not PrivateKeySize. +func Sign(privateKey PrivateKey, message []byte) []byte { + return ed25519.Sign(privateKey, message) +} + +// Verify reports whether sig is a valid signature of message by publicKey. It +// will panic if len(publicKey) is not PublicKeySize. +func Verify(publicKey PublicKey, message, sig []byte) bool { + return ed25519.Verify(publicKey, message, sig) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go new file mode 100644 index 00000000..45b5c966 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go @@ -0,0 +1,40 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.13 +// +build !go1.13 + +package poly1305 + +// Generic fallbacks for the math/bits intrinsics, copied from +// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had +// variable time fallbacks until Go 1.13. + +func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) { + sum = x + y + carry + carryOut = ((x & y) | ((x | y) &^ sum)) >> 63 + return +} + +func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) { + diff = x - y - borrow + borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63 + return +} + +func bitsMul64(x, y uint64) (hi, lo uint64) { + const mask32 = 1<<32 - 1 + x0 := x & mask32 + x1 := x >> 32 + y0 := y & mask32 + y1 := y >> 32 + w0 := x0 * y0 + t := x1*y0 + w0>>32 + w1 := t & mask32 + w2 := t >> 32 + w1 += x0 * y1 + hi = x1*y1 + w2 + w1>>32 + lo = x * y + return +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go new file mode 100644 index 00000000..ed52b341 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.13 +// +build go1.13 + +package poly1305 + +import "math/bits" + +func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) { + return bits.Add64(x, y, carry) +} + +func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) { + return bits.Sub64(x, y, borrow) +} + +func bitsMul64(x, y uint64) (hi, lo uint64) { + return bits.Mul64(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go new file mode 100644 index 00000000..f184b67d --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go @@ -0,0 +1,10 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego +// +build !amd64,!ppc64le,!s390x !gc purego + +package poly1305 + +type mac struct{ macGeneric } diff --git a/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go new file mode 100644 index 00000000..4aaea810 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go @@ -0,0 +1,99 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package poly1305 implements Poly1305 one-time message authentication code as +// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. +// +// Poly1305 is a fast, one-time authentication function. It is infeasible for an +// attacker to generate an authenticator for a message without the key. However, a +// key must only be used for a single message. Authenticating two different +// messages with the same key allows an attacker to forge authenticators for other +// messages with the same key. +// +// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was +// used with a fixed key in order to generate one-time keys from an nonce. +// However, in this package AES isn't used and the one-time key is specified +// directly. +package poly1305 + +import "crypto/subtle" + +// TagSize is the size, in bytes, of a poly1305 authenticator. +const TagSize = 16 + +// Sum generates an authenticator for msg using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + h := New(key) + h.Write(m) + h.Sum(out[:0]) +} + +// Verify returns true if mac is a valid authenticator for m with the given key. +func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { + var tmp [16]byte + Sum(&tmp, m, key) + return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 +} + +// New returns a new MAC computing an authentication +// tag of all data written to it with the given key. +// This allows writing the message progressively instead +// of passing it as a single slice. Common users should use +// the Sum function instead. +// +// The key must be unique for each message, as authenticating +// two different messages with the same key allows an attacker +// to forge messages at will. +func New(key *[32]byte) *MAC { + m := &MAC{} + initialize(key, &m.macState) + return m +} + +// MAC is an io.Writer computing an authentication tag +// of the data written to it. +// +// MAC cannot be used like common hash.Hash implementations, +// because using a poly1305 key twice breaks its security. +// Therefore writing data to a running MAC after calling +// Sum or Verify causes it to panic. +type MAC struct { + mac // platform-dependent implementation + + finalized bool +} + +// Size returns the number of bytes Sum will return. +func (h *MAC) Size() int { return TagSize } + +// Write adds more data to the running message authentication code. +// It never returns an error. +// +// It must not be called after the first call of Sum or Verify. +func (h *MAC) Write(p []byte) (n int, err error) { + if h.finalized { + panic("poly1305: write to MAC after Sum or Verify") + } + return h.mac.Write(p) +} + +// Sum computes the authenticator of all data written to the +// message authentication code. +func (h *MAC) Sum(b []byte) []byte { + var mac [TagSize]byte + h.mac.Sum(&mac) + h.finalized = true + return append(b, mac[:]...) +} + +// Verify returns whether the authenticator of all data written to +// the message authentication code matches the expected value. +func (h *MAC) Verify(expected []byte) bool { + var mac [TagSize]byte + h.mac.Sum(&mac) + h.finalized = true + return subtle.ConstantTimeCompare(expected, mac[:]) == 1 +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go new file mode 100644 index 00000000..6d522333 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go @@ -0,0 +1,48 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +package poly1305 + +//go:noescape +func update(state *macState, msg []byte) + +// mac is a wrapper for macGeneric that redirects calls that would have gone to +// updateGeneric to update. +// +// Its Write and Sum methods are otherwise identical to the macGeneric ones, but +// using function pointers would carry a major performance cost. +type mac struct{ macGeneric } + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + update(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + update(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +func (h *mac) Sum(out *[16]byte) { + state := h.macState + if h.offset > 0 { + update(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s new file mode 100644 index 00000000..1d74f0f8 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s @@ -0,0 +1,109 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +#include "textflag.h" + +#define POLY1305_ADD(msg, h0, h1, h2) \ + ADDQ 0(msg), h0; \ + ADCQ 8(msg), h1; \ + ADCQ $1, h2; \ + LEAQ 16(msg), msg + +#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ + MOVQ r0, AX; \ + MULQ h0; \ + MOVQ AX, t0; \ + MOVQ DX, t1; \ + MOVQ r0, AX; \ + MULQ h1; \ + ADDQ AX, t1; \ + ADCQ $0, DX; \ + MOVQ r0, t2; \ + IMULQ h2, t2; \ + ADDQ DX, t2; \ + \ + MOVQ r1, AX; \ + MULQ h0; \ + ADDQ AX, t1; \ + ADCQ $0, DX; \ + MOVQ DX, h0; \ + MOVQ r1, t3; \ + IMULQ h2, t3; \ + MOVQ r1, AX; \ + MULQ h1; \ + ADDQ AX, t2; \ + ADCQ DX, t3; \ + ADDQ h0, t2; \ + ADCQ $0, t3; \ + \ + MOVQ t0, h0; \ + MOVQ t1, h1; \ + MOVQ t2, h2; \ + ANDQ $3, h2; \ + MOVQ t2, t0; \ + ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ + ADDQ t0, h0; \ + ADCQ t3, h1; \ + ADCQ $0, h2; \ + SHRQ $2, t3, t2; \ + SHRQ $2, t3; \ + ADDQ t2, h0; \ + ADCQ t3, h1; \ + ADCQ $0, h2 + +// func update(state *[7]uint64, msg []byte) +TEXT ·update(SB), $0-32 + MOVQ state+0(FP), DI + MOVQ msg_base+8(FP), SI + MOVQ msg_len+16(FP), R15 + + MOVQ 0(DI), R8 // h0 + MOVQ 8(DI), R9 // h1 + MOVQ 16(DI), R10 // h2 + MOVQ 24(DI), R11 // r0 + MOVQ 32(DI), R12 // r1 + + CMPQ R15, $16 + JB bytes_between_0_and_15 + +loop: + POLY1305_ADD(SI, R8, R9, R10) + +multiply: + POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) + SUBQ $16, R15 + CMPQ R15, $16 + JAE loop + +bytes_between_0_and_15: + TESTQ R15, R15 + JZ done + MOVQ $1, BX + XORQ CX, CX + XORQ R13, R13 + ADDQ R15, SI + +flush_buffer: + SHLQ $8, BX, CX + SHLQ $8, BX + MOVB -1(SI), R13 + XORQ R13, BX + DECQ SI + DECQ R15 + JNZ flush_buffer + + ADDQ BX, R8 + ADCQ CX, R9 + ADCQ $0, R10 + MOVQ $16, R15 + JMP multiply + +done: + MOVQ R8, 0(DI) + MOVQ R9, 8(DI) + MOVQ R10, 16(DI) + RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go new file mode 100644 index 00000000..e041da5e --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go @@ -0,0 +1,309 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file provides the generic implementation of Sum and MAC. Other files +// might provide optimized assembly implementations of some of this code. + +package poly1305 + +import "encoding/binary" + +// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag +// for a 64 bytes message is approximately +// +// s + m[0:16] * r⁴ + m[16:32] * r³ + m[32:48] * r² + m[48:64] * r mod 2¹³⁰ - 5 +// +// for some secret r and s. It can be computed sequentially like +// +// for len(msg) > 0: +// h += read(msg, 16) +// h *= r +// h %= 2¹³⁰ - 5 +// return h + s +// +// All the complexity is about doing performant constant-time math on numbers +// larger than any available numeric type. + +func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { + h := newMACGeneric(key) + h.Write(msg) + h.Sum(out) +} + +func newMACGeneric(key *[32]byte) macGeneric { + m := macGeneric{} + initialize(key, &m.macState) + return m +} + +// macState holds numbers in saturated 64-bit little-endian limbs. That is, +// the value of [x0, x1, x2] is x[0] + x[1] * 2⁶⁴ + x[2] * 2¹²⁸. +type macState struct { + // h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but + // can grow larger during and after rounds. It must, however, remain below + // 2 * (2¹³⁰ - 5). + h [3]uint64 + // r and s are the private key components. + r [2]uint64 + s [2]uint64 +} + +type macGeneric struct { + macState + + buffer [TagSize]byte + offset int +} + +// Write splits the incoming message into TagSize chunks, and passes them to +// update. It buffers incomplete chunks. +func (h *macGeneric) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + updateGeneric(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + updateGeneric(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +// Sum flushes the last incomplete chunk from the buffer, if any, and generates +// the MAC output. It does not modify its state, in order to allow for multiple +// calls to Sum, even if no Write is allowed after Sum. +func (h *macGeneric) Sum(out *[TagSize]byte) { + state := h.macState + if h.offset > 0 { + updateGeneric(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} + +// [rMask0, rMask1] is the specified Poly1305 clamping mask in little-endian. It +// clears some bits of the secret coefficient to make it possible to implement +// multiplication more efficiently. +const ( + rMask0 = 0x0FFFFFFC0FFFFFFF + rMask1 = 0x0FFFFFFC0FFFFFFC +) + +// initialize loads the 256-bit key into the two 128-bit secret values r and s. +func initialize(key *[32]byte, m *macState) { + m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 + m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 + m.s[0] = binary.LittleEndian.Uint64(key[16:24]) + m.s[1] = binary.LittleEndian.Uint64(key[24:32]) +} + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +func mul64(a, b uint64) uint128 { + hi, lo := bitsMul64(a, b) + return uint128{lo, hi} +} + +func add128(a, b uint128) uint128 { + lo, c := bitsAdd64(a.lo, b.lo, 0) + hi, c := bitsAdd64(a.hi, b.hi, c) + if c != 0 { + panic("poly1305: unexpected overflow") + } + return uint128{lo, hi} +} + +func shiftRightBy2(a uint128) uint128 { + a.lo = a.lo>>2 | (a.hi&3)<<62 + a.hi = a.hi >> 2 + return a +} + +// updateGeneric absorbs msg into the state.h accumulator. For each chunk m of +// 128 bits of message, it computes +// +// h₊ = (h + m) * r mod 2¹³⁰ - 5 +// +// If the msg length is not a multiple of TagSize, it assumes the last +// incomplete chunk is the final one. +func updateGeneric(state *macState, msg []byte) { + h0, h1, h2 := state.h[0], state.h[1], state.h[2] + r0, r1 := state.r[0], state.r[1] + + for len(msg) > 0 { + var c uint64 + + // For the first step, h + m, we use a chain of bits.Add64 intrinsics. + // The resulting value of h might exceed 2¹³⁰ - 5, but will be partially + // reduced at the end of the multiplication below. + // + // The spec requires us to set a bit just above the message size, not to + // hide leading zeroes. For full chunks, that's 1 << 128, so we can just + // add 1 to the most significant (2¹²⁸) limb, h2. + if len(msg) >= TagSize { + h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0) + h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c) + h2 += c + 1 + + msg = msg[TagSize:] + } else { + var buf [TagSize]byte + copy(buf[:], msg) + buf[len(msg)] = 1 + + h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0) + h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c) + h2 += c + + msg = nil + } + + // Multiplication of big number limbs is similar to elementary school + // columnar multiplication. Instead of digits, there are 64-bit limbs. + // + // We are multiplying a 3 limbs number, h, by a 2 limbs number, r. + // + // h2 h1 h0 x + // r1 r0 = + // ---------------- + // h2r0 h1r0 h0r0 <-- individual 128-bit products + // + h2r1 h1r1 h0r1 + // ------------------------ + // m3 m2 m1 m0 <-- result in 128-bit overlapping limbs + // ------------------------ + // m3.hi m2.hi m1.hi m0.hi <-- carry propagation + // + m3.lo m2.lo m1.lo m0.lo + // ------------------------------- + // t4 t3 t2 t1 t0 <-- final result in 64-bit limbs + // + // The main difference from pen-and-paper multiplication is that we do + // carry propagation in a separate step, as if we wrote two digit sums + // at first (the 128-bit limbs), and then carried the tens all at once. + + h0r0 := mul64(h0, r0) + h1r0 := mul64(h1, r0) + h2r0 := mul64(h2, r0) + h0r1 := mul64(h0, r1) + h1r1 := mul64(h1, r1) + h2r1 := mul64(h2, r1) + + // Since h2 is known to be at most 7 (5 + 1 + 1), and r0 and r1 have their + // top 4 bits cleared by rMask{0,1}, we know that their product is not going + // to overflow 64 bits, so we can ignore the high part of the products. + // + // This also means that the product doesn't have a fifth limb (t4). + if h2r0.hi != 0 { + panic("poly1305: unexpected overflow") + } + if h2r1.hi != 0 { + panic("poly1305: unexpected overflow") + } + + m0 := h0r0 + m1 := add128(h1r0, h0r1) // These two additions don't overflow thanks again + m2 := add128(h2r0, h1r1) // to the 4 masked bits at the top of r0 and r1. + m3 := h2r1 + + t0 := m0.lo + t1, c := bitsAdd64(m1.lo, m0.hi, 0) + t2, c := bitsAdd64(m2.lo, m1.hi, c) + t3, _ := bitsAdd64(m3.lo, m2.hi, c) + + // Now we have the result as 4 64-bit limbs, and we need to reduce it + // modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do + // a cheap partial reduction according to the reduction identity + // + // c * 2¹³⁰ + n = c * 5 + n mod 2¹³⁰ - 5 + // + // because 2¹³⁰ = 5 mod 2¹³⁰ - 5. Partial reduction since the result is + // likely to be larger than 2¹³⁰ - 5, but still small enough to fit the + // assumptions we make about h in the rest of the code. + // + // See also https://speakerdeck.com/gtank/engineering-prime-numbers?slide=23 + + // We split the final result at the 2¹³⁰ mark into h and cc, the carry. + // Note that the carry bits are effectively shifted left by 2, in other + // words, cc = c * 4 for the c in the reduction identity. + h0, h1, h2 = t0, t1, t2&maskLow2Bits + cc := uint128{t2 & maskNotLow2Bits, t3} + + // To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c. + + h0, c = bitsAdd64(h0, cc.lo, 0) + h1, c = bitsAdd64(h1, cc.hi, c) + h2 += c + + cc = shiftRightBy2(cc) + + h0, c = bitsAdd64(h0, cc.lo, 0) + h1, c = bitsAdd64(h1, cc.hi, c) + h2 += c + + // h2 is at most 3 + 1 + 1 = 5, making the whole of h at most + // + // 5 * 2¹²⁸ + (2¹²⁸ - 1) = 6 * 2¹²⁸ - 1 + } + + state.h[0], state.h[1], state.h[2] = h0, h1, h2 +} + +const ( + maskLow2Bits uint64 = 0x0000000000000003 + maskNotLow2Bits uint64 = ^maskLow2Bits +) + +// select64 returns x if v == 1 and y if v == 0, in constant time. +func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y } + +// [p0, p1, p2] is 2¹³⁰ - 5 in little endian order. +const ( + p0 = 0xFFFFFFFFFFFFFFFB + p1 = 0xFFFFFFFFFFFFFFFF + p2 = 0x0000000000000003 +) + +// finalize completes the modular reduction of h and computes +// +// out = h + s mod 2¹²⁸ +func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) { + h0, h1, h2 := h[0], h[1], h[2] + + // After the partial reduction in updateGeneric, h might be more than + // 2¹³⁰ - 5, but will be less than 2 * (2¹³⁰ - 5). To complete the reduction + // in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the + // result if the subtraction underflows, and t otherwise. + + hMinusP0, b := bitsSub64(h0, p0, 0) + hMinusP1, b := bitsSub64(h1, p1, b) + _, b = bitsSub64(h2, p2, b) + + // h = h if h < p else h - p + h0 = select64(b, h0, hMinusP0) + h1 = select64(b, h1, hMinusP1) + + // Finally, we compute the last Poly1305 step + // + // tag = h + s mod 2¹²⁸ + // + // by just doing a wide addition with the 128 low bits of h and discarding + // the overflow. + h0, c := bitsAdd64(h0, s[0], 0) + h1, _ = bitsAdd64(h1, s[1], c) + + binary.LittleEndian.PutUint64(out[0:8], h0) + binary.LittleEndian.PutUint64(out[8:16], h1) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go new file mode 100644 index 00000000..4a069941 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go @@ -0,0 +1,48 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +package poly1305 + +//go:noescape +func update(state *macState, msg []byte) + +// mac is a wrapper for macGeneric that redirects calls that would have gone to +// updateGeneric to update. +// +// Its Write and Sum methods are otherwise identical to the macGeneric ones, but +// using function pointers would carry a major performance cost. +type mac struct{ macGeneric } + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + update(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + update(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +func (h *mac) Sum(out *[16]byte) { + state := h.macState + if h.offset > 0 { + update(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s new file mode 100644 index 00000000..58422aad --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s @@ -0,0 +1,182 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +#include "textflag.h" + +// This was ported from the amd64 implementation. + +#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \ + MOVD (msg), t0; \ + MOVD 8(msg), t1; \ + MOVD $1, t2; \ + ADDC t0, h0, h0; \ + ADDE t1, h1, h1; \ + ADDE t2, h2; \ + ADD $16, msg + +#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ + MULLD r0, h0, t0; \ + MULLD r0, h1, t4; \ + MULHDU r0, h0, t1; \ + MULHDU r0, h1, t5; \ + ADDC t4, t1, t1; \ + MULLD r0, h2, t2; \ + ADDZE t5; \ + MULHDU r1, h0, t4; \ + MULLD r1, h0, h0; \ + ADD t5, t2, t2; \ + ADDC h0, t1, t1; \ + MULLD h2, r1, t3; \ + ADDZE t4, h0; \ + MULHDU r1, h1, t5; \ + MULLD r1, h1, t4; \ + ADDC t4, t2, t2; \ + ADDE t5, t3, t3; \ + ADDC h0, t2, t2; \ + MOVD $-4, t4; \ + MOVD t0, h0; \ + MOVD t1, h1; \ + ADDZE t3; \ + ANDCC $3, t2, h2; \ + AND t2, t4, t0; \ + ADDC t0, h0, h0; \ + ADDE t3, h1, h1; \ + SLD $62, t3, t4; \ + SRD $2, t2; \ + ADDZE h2; \ + OR t4, t2, t2; \ + SRD $2, t3; \ + ADDC t2, h0, h0; \ + ADDE t3, h1, h1; \ + ADDZE h2 + +DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF +DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC +GLOBL ·poly1305Mask<>(SB), RODATA, $16 + +// func update(state *[7]uint64, msg []byte) +TEXT ·update(SB), $0-32 + MOVD state+0(FP), R3 + MOVD msg_base+8(FP), R4 + MOVD msg_len+16(FP), R5 + + MOVD 0(R3), R8 // h0 + MOVD 8(R3), R9 // h1 + MOVD 16(R3), R10 // h2 + MOVD 24(R3), R11 // r0 + MOVD 32(R3), R12 // r1 + + CMP R5, $16 + BLT bytes_between_0_and_15 + +loop: + POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) + +multiply: + POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) + ADD $-16, R5 + CMP R5, $16 + BGE loop + +bytes_between_0_and_15: + CMP R5, $0 + BEQ done + MOVD $0, R16 // h0 + MOVD $0, R17 // h1 + +flush_buffer: + CMP R5, $8 + BLE just1 + + MOVD $8, R21 + SUB R21, R5, R21 + + // Greater than 8 -- load the rightmost remaining bytes in msg + // and put into R17 (h1) + MOVD (R4)(R21), R17 + MOVD $16, R22 + + // Find the offset to those bytes + SUB R5, R22, R22 + SLD $3, R22 + + // Shift to get only the bytes in msg + SRD R22, R17, R17 + + // Put 1 at high end + MOVD $1, R23 + SLD $3, R21 + SLD R21, R23, R23 + OR R23, R17, R17 + + // Remainder is 8 + MOVD $8, R5 + +just1: + CMP R5, $8 + BLT less8 + + // Exactly 8 + MOVD (R4), R16 + + CMP R17, $0 + + // Check if we've already set R17; if not + // set 1 to indicate end of msg. + BNE carry + MOVD $1, R17 + BR carry + +less8: + MOVD $0, R16 // h0 + MOVD $0, R22 // shift count + CMP R5, $4 + BLT less4 + MOVWZ (R4), R16 + ADD $4, R4 + ADD $-4, R5 + MOVD $32, R22 + +less4: + CMP R5, $2 + BLT less2 + MOVHZ (R4), R21 + SLD R22, R21, R21 + OR R16, R21, R16 + ADD $16, R22 + ADD $-2, R5 + ADD $2, R4 + +less2: + CMP R5, $0 + BEQ insert1 + MOVBZ (R4), R21 + SLD R22, R21, R21 + OR R16, R21, R16 + ADD $8, R22 + +insert1: + // Insert 1 at end of msg + MOVD $1, R21 + SLD R22, R21, R21 + OR R16, R21, R16 + +carry: + // Add new values to h0, h1, h2 + ADDC R16, R8 + ADDE R17, R9 + ADDZE R10, R10 + MOVD $16, R5 + ADD R5, R4 + BR multiply + +done: + // Save h0, h1, h2 in state + MOVD R8, 0(R3) + MOVD R9, 8(R3) + MOVD R10, 16(R3) + RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go new file mode 100644 index 00000000..ec959668 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go @@ -0,0 +1,77 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +package poly1305 + +import ( + "golang.org/x/sys/cpu" +) + +// updateVX is an assembly implementation of Poly1305 that uses vector +// instructions. It must only be called if the vector facility (vx) is +// available. +// +//go:noescape +func updateVX(state *macState, msg []byte) + +// mac is a replacement for macGeneric that uses a larger buffer and redirects +// calls that would have gone to updateGeneric to updateVX if the vector +// facility is installed. +// +// A larger buffer is required for good performance because the vector +// implementation has a higher fixed cost per call than the generic +// implementation. +type mac struct { + macState + + buffer [16 * TagSize]byte // size must be a multiple of block size (16) + offset int +} + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < len(h.buffer) { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + if cpu.S390X.HasVX { + updateVX(&h.macState, h.buffer[:]) + } else { + updateGeneric(&h.macState, h.buffer[:]) + } + } + + tail := len(p) % len(h.buffer) // number of bytes to copy into buffer + body := len(p) - tail // number of bytes to process now + if body > 0 { + if cpu.S390X.HasVX { + updateVX(&h.macState, p[:body]) + } else { + updateGeneric(&h.macState, p[:body]) + } + } + h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0 + return nn, nil +} + +func (h *mac) Sum(out *[TagSize]byte) { + state := h.macState + remainder := h.buffer[:h.offset] + + // Use the generic implementation if we have 2 or fewer blocks left + // to sum. The vector implementation has a higher startup time. + if cpu.S390X.HasVX && len(remainder) > 2*TagSize { + updateVX(&state, remainder) + } else if len(remainder) > 0 { + updateGeneric(&state, remainder) + } + finalize(out, &state.h, &state.s) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s new file mode 100644 index 00000000..aa9e0494 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s @@ -0,0 +1,504 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego +// +build gc,!purego + +#include "textflag.h" + +// This implementation of Poly1305 uses the vector facility (vx) +// to process up to 2 blocks (32 bytes) per iteration using an +// algorithm based on the one described in: +// +// NEON crypto, Daniel J. Bernstein & Peter Schwabe +// https://cryptojedi.org/papers/neoncrypto-20120320.pdf +// +// This algorithm uses 5 26-bit limbs to represent a 130-bit +// value. These limbs are, for the most part, zero extended and +// placed into 64-bit vector register elements. Each vector +// register is 128-bits wide and so holds 2 of these elements. +// Using 26-bit limbs allows us plenty of headroom to accommodate +// accumulations before and after multiplication without +// overflowing either 32-bits (before multiplication) or 64-bits +// (after multiplication). +// +// In order to parallelise the operations required to calculate +// the sum we use two separate accumulators and then sum those +// in an extra final step. For compatibility with the generic +// implementation we perform this summation at the end of every +// updateVX call. +// +// To use two accumulators we must multiply the message blocks +// by r² rather than r. Only the final message block should be +// multiplied by r. +// +// Example: +// +// We want to calculate the sum (h) for a 64 byte message (m): +// +// h = m[0:16]r⁴ + m[16:32]r³ + m[32:48]r² + m[48:64]r +// +// To do this we split the calculation into the even indices +// and odd indices of the message. These form our SIMD 'lanes': +// +// h = m[ 0:16]r⁴ + m[32:48]r² + <- lane 0 +// m[16:32]r³ + m[48:64]r <- lane 1 +// +// To calculate this iteratively we refactor so that both lanes +// are written in terms of r² and r: +// +// h = (m[ 0:16]r² + m[32:48])r² + <- lane 0 +// (m[16:32]r² + m[48:64])r <- lane 1 +// ^ ^ +// | coefficients for second iteration +// coefficients for first iteration +// +// So in this case we would have two iterations. In the first +// both lanes are multiplied by r². In the second only the +// first lane is multiplied by r² and the second lane is +// instead multiplied by r. This gives use the odd and even +// powers of r that we need from the original equation. +// +// Notation: +// +// h - accumulator +// r - key +// m - message +// +// [a, b] - SIMD register holding two 64-bit values +// [a, b, c, d] - SIMD register holding four 32-bit values +// xᵢ[n] - limb n of variable x with bit width i +// +// Limbs are expressed in little endian order, so for 26-bit +// limbs x₂₆[4] will be the most significant limb and x₂₆[0] +// will be the least significant limb. + +// masking constants +#define MOD24 V0 // [0x0000000000ffffff, 0x0000000000ffffff] - mask low 24-bits +#define MOD26 V1 // [0x0000000003ffffff, 0x0000000003ffffff] - mask low 26-bits + +// expansion constants (see EXPAND macro) +#define EX0 V2 +#define EX1 V3 +#define EX2 V4 + +// key (r², r or 1 depending on context) +#define R_0 V5 +#define R_1 V6 +#define R_2 V7 +#define R_3 V8 +#define R_4 V9 + +// precalculated coefficients (5r², 5r or 0 depending on context) +#define R5_1 V10 +#define R5_2 V11 +#define R5_3 V12 +#define R5_4 V13 + +// message block (m) +#define M_0 V14 +#define M_1 V15 +#define M_2 V16 +#define M_3 V17 +#define M_4 V18 + +// accumulator (h) +#define H_0 V19 +#define H_1 V20 +#define H_2 V21 +#define H_3 V22 +#define H_4 V23 + +// temporary registers (for short-lived values) +#define T_0 V24 +#define T_1 V25 +#define T_2 V26 +#define T_3 V27 +#define T_4 V28 + +GLOBL ·constants<>(SB), RODATA, $0x30 +// EX0 +DATA ·constants<>+0x00(SB)/8, $0x0006050403020100 +DATA ·constants<>+0x08(SB)/8, $0x1016151413121110 +// EX1 +DATA ·constants<>+0x10(SB)/8, $0x060c0b0a09080706 +DATA ·constants<>+0x18(SB)/8, $0x161c1b1a19181716 +// EX2 +DATA ·constants<>+0x20(SB)/8, $0x0d0d0d0d0d0f0e0d +DATA ·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d + +// MULTIPLY multiplies each lane of f and g, partially reduced +// modulo 2¹³⁰ - 5. The result, h, consists of partial products +// in each lane that need to be reduced further to produce the +// final result. +// +// h₁₃₀ = (f₁₃₀g₁₃₀) % 2¹³⁰ + (5f₁₃₀g₁₃₀) / 2¹³⁰ +// +// Note that the multiplication by 5 of the high bits is +// achieved by precalculating the multiplication of four of the +// g coefficients by 5. These are g51-g54. +#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ + VMLOF f0, g0, h0 \ + VMLOF f0, g3, h3 \ + VMLOF f0, g1, h1 \ + VMLOF f0, g4, h4 \ + VMLOF f0, g2, h2 \ + VMLOF f1, g54, T_0 \ + VMLOF f1, g2, T_3 \ + VMLOF f1, g0, T_1 \ + VMLOF f1, g3, T_4 \ + VMLOF f1, g1, T_2 \ + VMALOF f2, g53, h0, h0 \ + VMALOF f2, g1, h3, h3 \ + VMALOF f2, g54, h1, h1 \ + VMALOF f2, g2, h4, h4 \ + VMALOF f2, g0, h2, h2 \ + VMALOF f3, g52, T_0, T_0 \ + VMALOF f3, g0, T_3, T_3 \ + VMALOF f3, g53, T_1, T_1 \ + VMALOF f3, g1, T_4, T_4 \ + VMALOF f3, g54, T_2, T_2 \ + VMALOF f4, g51, h0, h0 \ + VMALOF f4, g54, h3, h3 \ + VMALOF f4, g52, h1, h1 \ + VMALOF f4, g0, h4, h4 \ + VMALOF f4, g53, h2, h2 \ + VAG T_0, h0, h0 \ + VAG T_3, h3, h3 \ + VAG T_1, h1, h1 \ + VAG T_4, h4, h4 \ + VAG T_2, h2, h2 + +// REDUCE performs the following carry operations in four +// stages, as specified in Bernstein & Schwabe: +// +// 1: h₂₆[0]->h₂₆[1] h₂₆[3]->h₂₆[4] +// 2: h₂₆[1]->h₂₆[2] h₂₆[4]->h₂₆[0] +// 3: h₂₆[0]->h₂₆[1] h₂₆[2]->h₂₆[3] +// 4: h₂₆[3]->h₂₆[4] +// +// The result is that all of the limbs are limited to 26-bits +// except for h₂₆[1] and h₂₆[4] which are limited to 27-bits. +// +// Note that although each limb is aligned at 26-bit intervals +// they may contain values that exceed 2²⁶ - 1, hence the need +// to carry the excess bits in each limb. +#define REDUCE(h0, h1, h2, h3, h4) \ + VESRLG $26, h0, T_0 \ + VESRLG $26, h3, T_1 \ + VN MOD26, h0, h0 \ + VN MOD26, h3, h3 \ + VAG T_0, h1, h1 \ + VAG T_1, h4, h4 \ + VESRLG $26, h1, T_2 \ + VESRLG $26, h4, T_3 \ + VN MOD26, h1, h1 \ + VN MOD26, h4, h4 \ + VESLG $2, T_3, T_4 \ + VAG T_3, T_4, T_4 \ + VAG T_2, h2, h2 \ + VAG T_4, h0, h0 \ + VESRLG $26, h2, T_0 \ + VESRLG $26, h0, T_1 \ + VN MOD26, h2, h2 \ + VN MOD26, h0, h0 \ + VAG T_0, h3, h3 \ + VAG T_1, h1, h1 \ + VESRLG $26, h3, T_2 \ + VN MOD26, h3, h3 \ + VAG T_2, h4, h4 + +// EXPAND splits the 128-bit little-endian values in0 and in1 +// into 26-bit big-endian limbs and places the results into +// the first and second lane of d₂₆[0:4] respectively. +// +// The EX0, EX1 and EX2 constants are arrays of byte indices +// for permutation. The permutation both reverses the bytes +// in the input and ensures the bytes are copied into the +// destination limb ready to be shifted into their final +// position. +#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ + VPERM in0, in1, EX0, d0 \ + VPERM in0, in1, EX1, d2 \ + VPERM in0, in1, EX2, d4 \ + VESRLG $26, d0, d1 \ + VESRLG $30, d2, d3 \ + VESRLG $4, d2, d2 \ + VN MOD26, d0, d0 \ // [in0₂₆[0], in1₂₆[0]] + VN MOD26, d3, d3 \ // [in0₂₆[3], in1₂₆[3]] + VN MOD26, d1, d1 \ // [in0₂₆[1], in1₂₆[1]] + VN MOD24, d4, d4 \ // [in0₂₆[4], in1₂₆[4]] + VN MOD26, d2, d2 // [in0₂₆[2], in1₂₆[2]] + +// func updateVX(state *macState, msg []byte) +TEXT ·updateVX(SB), NOSPLIT, $0 + MOVD state+0(FP), R1 + LMG msg+8(FP), R2, R3 // R2=msg_base, R3=msg_len + + // load EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + // generate masks + VGMG $(64-24), $63, MOD24 // [0x00ffffff, 0x00ffffff] + VGMG $(64-26), $63, MOD26 // [0x03ffffff, 0x03ffffff] + + // load h (accumulator) and r (key) from state + VZERO T_1 // [0, 0] + VL 0(R1), T_0 // [h₆₄[0], h₆₄[1]] + VLEG $0, 16(R1), T_1 // [h₆₄[2], 0] + VL 24(R1), T_2 // [r₆₄[0], r₆₄[1]] + VPDI $0, T_0, T_2, T_3 // [h₆₄[0], r₆₄[0]] + VPDI $5, T_0, T_2, T_4 // [h₆₄[1], r₆₄[1]] + + // unpack h and r into 26-bit limbs + // note: h₆₄[2] may have the low 3 bits set, so h₂₆[4] is a 27-bit value + VN MOD26, T_3, H_0 // [h₂₆[0], r₂₆[0]] + VZERO H_1 // [0, 0] + VZERO H_3 // [0, 0] + VGMG $(64-12-14), $(63-12), T_0 // [0x03fff000, 0x03fff000] - 26-bit mask with low 12 bits masked out + VESLG $24, T_1, T_1 // [h₆₄[2]<<24, 0] + VERIMG $-26&63, T_3, MOD26, H_1 // [h₂₆[1], r₂₆[1]] + VESRLG $+52&63, T_3, H_2 // [h₂₆[2], r₂₆[2]] - low 12 bits only + VERIMG $-14&63, T_4, MOD26, H_3 // [h₂₆[1], r₂₆[1]] + VESRLG $40, T_4, H_4 // [h₂₆[4], r₂₆[4]] - low 24 bits only + VERIMG $+12&63, T_4, T_0, H_2 // [h₂₆[2], r₂₆[2]] - complete + VO T_1, H_4, H_4 // [h₂₆[4], r₂₆[4]] - complete + + // replicate r across all 4 vector elements + VREPF $3, H_0, R_0 // [r₂₆[0], r₂₆[0], r₂₆[0], r₂₆[0]] + VREPF $3, H_1, R_1 // [r₂₆[1], r₂₆[1], r₂₆[1], r₂₆[1]] + VREPF $3, H_2, R_2 // [r₂₆[2], r₂₆[2], r₂₆[2], r₂₆[2]] + VREPF $3, H_3, R_3 // [r₂₆[3], r₂₆[3], r₂₆[3], r₂₆[3]] + VREPF $3, H_4, R_4 // [r₂₆[4], r₂₆[4], r₂₆[4], r₂₆[4]] + + // zero out lane 1 of h + VLEIG $1, $0, H_0 // [h₂₆[0], 0] + VLEIG $1, $0, H_1 // [h₂₆[1], 0] + VLEIG $1, $0, H_2 // [h₂₆[2], 0] + VLEIG $1, $0, H_3 // [h₂₆[3], 0] + VLEIG $1, $0, H_4 // [h₂₆[4], 0] + + // calculate 5r (ignore least significant limb) + VREPIF $5, T_0 + VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r₂₆[1], 5r₂₆[1], 5r₂₆[1]] + VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r₂₆[2], 5r₂₆[2], 5r₂₆[2]] + VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r₂₆[3], 5r₂₆[3], 5r₂₆[3]] + VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r₂₆[4], 5r₂₆[4], 5r₂₆[4]] + + // skip r² calculation if we are only calculating one block + CMPBLE R3, $16, skip + + // calculate r² + MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, M_0, M_1, M_2, M_3, M_4) + REDUCE(M_0, M_1, M_2, M_3, M_4) + VGBM $0x0f0f, T_0 + VERIMG $0, M_0, T_0, R_0 // [r₂₆[0], r²₂₆[0], r₂₆[0], r²₂₆[0]] + VERIMG $0, M_1, T_0, R_1 // [r₂₆[1], r²₂₆[1], r₂₆[1], r²₂₆[1]] + VERIMG $0, M_2, T_0, R_2 // [r₂₆[2], r²₂₆[2], r₂₆[2], r²₂₆[2]] + VERIMG $0, M_3, T_0, R_3 // [r₂₆[3], r²₂₆[3], r₂₆[3], r²₂₆[3]] + VERIMG $0, M_4, T_0, R_4 // [r₂₆[4], r²₂₆[4], r₂₆[4], r²₂₆[4]] + + // calculate 5r² (ignore least significant limb) + VREPIF $5, T_0 + VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r²₂₆[1], 5r₂₆[1], 5r²₂₆[1]] + VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r²₂₆[2], 5r₂₆[2], 5r²₂₆[2]] + VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r²₂₆[3], 5r₂₆[3], 5r²₂₆[3]] + VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r²₂₆[4], 5r₂₆[4], 5r²₂₆[4]] + +loop: + CMPBLE R3, $32, b2 // 2 or fewer blocks remaining, need to change key coefficients + + // load next 2 blocks from message + VLM (R2), T_0, T_1 + + // update message slice + SUB $32, R3 + MOVD $32(R2), R2 + + // unpack message blocks into 26-bit big-endian limbs + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // add 2¹²⁸ to each message block value + VLEIB $4, $1, M_4 + VLEIB $12, $1, M_4 + +multiply: + // accumulate the incoming message + VAG H_0, M_0, M_0 + VAG H_3, M_3, M_3 + VAG H_1, M_1, M_1 + VAG H_4, M_4, M_4 + VAG H_2, M_2, M_2 + + // multiply the accumulator by the key coefficient + MULTIPLY(M_0, M_1, M_2, M_3, M_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) + + // carry and partially reduce the partial products + REDUCE(H_0, H_1, H_2, H_3, H_4) + + CMPBNE R3, $0, loop + +finish: + // sum lane 0 and lane 1 and put the result in lane 1 + VZERO T_0 + VSUMQG H_0, T_0, H_0 + VSUMQG H_3, T_0, H_3 + VSUMQG H_1, T_0, H_1 + VSUMQG H_4, T_0, H_4 + VSUMQG H_2, T_0, H_2 + + // reduce again after summation + // TODO(mundaym): there might be a more efficient way to do this + // now that we only have 1 active lane. For example, we could + // simultaneously pack the values as we reduce them. + REDUCE(H_0, H_1, H_2, H_3, H_4) + + // carry h[1] through to h[4] so that only h[4] can exceed 2²⁶ - 1 + // TODO(mundaym): in testing this final carry was unnecessary. + // Needs a proof before it can be removed though. + VESRLG $26, H_1, T_1 + VN MOD26, H_1, H_1 + VAQ T_1, H_2, H_2 + VESRLG $26, H_2, T_2 + VN MOD26, H_2, H_2 + VAQ T_2, H_3, H_3 + VESRLG $26, H_3, T_3 + VN MOD26, H_3, H_3 + VAQ T_3, H_4, H_4 + + // h is now < 2(2¹³⁰ - 5) + // Pack each lane in h₂₆[0:4] into h₁₂₈[0:1]. + VESLG $26, H_1, H_1 + VESLG $26, H_3, H_3 + VO H_0, H_1, H_0 + VO H_2, H_3, H_2 + VESLG $4, H_2, H_2 + VLEIB $7, $48, H_1 + VSLB H_1, H_2, H_2 + VO H_0, H_2, H_0 + VLEIB $7, $104, H_1 + VSLB H_1, H_4, H_3 + VO H_3, H_0, H_0 + VLEIB $7, $24, H_1 + VSRLB H_1, H_4, H_1 + + // update state + VSTEG $1, H_0, 0(R1) + VSTEG $0, H_0, 8(R1) + VSTEG $1, H_1, 16(R1) + RET + +b2: // 2 or fewer blocks remaining + CMPBLE R3, $16, b1 + + // Load the 2 remaining blocks (17-32 bytes remaining). + MOVD $-17(R3), R0 // index of final byte to load modulo 16 + VL (R2), T_0 // load full 16 byte block + VLL R0, 16(R2), T_1 // load final (possibly partial) block and pad with zeros to 16 bytes + + // The Poly1305 algorithm requires that a 1 bit be appended to + // each message block. If the final block is less than 16 bytes + // long then it is easiest to insert the 1 before the message + // block is split into 26-bit limbs. If, on the other hand, the + // final message block is 16 bytes long then we append the 1 bit + // after expansion as normal. + MOVBZ $1, R0 + MOVD $-16(R3), R3 // index of byte in last block to insert 1 at (could be 16) + CMPBEQ R3, $16, 2(PC) // skip the insertion if the final block is 16 bytes long + VLVGB R3, R0, T_1 // insert 1 into the byte at index R3 + + // Split both blocks into 26-bit limbs in the appropriate lanes. + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // Append a 1 byte to the end of the second to last block. + VLEIB $4, $1, M_4 + + // Append a 1 byte to the end of the last block only if it is a + // full 16 byte block. + CMPBNE R3, $16, 2(PC) + VLEIB $12, $1, M_4 + + // Finally, set up the coefficients for the final multiplication. + // We have previously saved r and 5r in the 32-bit even indexes + // of the R_[0-4] and R5_[1-4] coefficient registers. + // + // We want lane 0 to be multiplied by r² so that can be kept the + // same. We want lane 1 to be multiplied by r so we need to move + // the saved r value into the 32-bit odd index in lane 1 by + // rotating the 64-bit lane by 32. + VGBM $0x00ff, T_0 // [0, 0xffffffffffffffff] - mask lane 1 only + VERIMG $32, R_0, T_0, R_0 // [_, r²₂₆[0], _, r₂₆[0]] + VERIMG $32, R_1, T_0, R_1 // [_, r²₂₆[1], _, r₂₆[1]] + VERIMG $32, R_2, T_0, R_2 // [_, r²₂₆[2], _, r₂₆[2]] + VERIMG $32, R_3, T_0, R_3 // [_, r²₂₆[3], _, r₂₆[3]] + VERIMG $32, R_4, T_0, R_4 // [_, r²₂₆[4], _, r₂₆[4]] + VERIMG $32, R5_1, T_0, R5_1 // [_, 5r²₂₆[1], _, 5r₂₆[1]] + VERIMG $32, R5_2, T_0, R5_2 // [_, 5r²₂₆[2], _, 5r₂₆[2]] + VERIMG $32, R5_3, T_0, R5_3 // [_, 5r²₂₆[3], _, 5r₂₆[3]] + VERIMG $32, R5_4, T_0, R5_4 // [_, 5r²₂₆[4], _, 5r₂₆[4]] + + MOVD $0, R3 + BR multiply + +skip: + CMPBEQ R3, $0, finish + +b1: // 1 block remaining + + // Load the final block (1-16 bytes). This will be placed into + // lane 0. + MOVD $-1(R3), R0 + VLL R0, (R2), T_0 // pad to 16 bytes with zeros + + // The Poly1305 algorithm requires that a 1 bit be appended to + // each message block. If the final block is less than 16 bytes + // long then it is easiest to insert the 1 before the message + // block is split into 26-bit limbs. If, on the other hand, the + // final message block is 16 bytes long then we append the 1 bit + // after expansion as normal. + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_0 + + // Set the message block in lane 1 to the value 0 so that it + // can be accumulated without affecting the final result. + VZERO T_1 + + // Split the final message block into 26-bit limbs in lane 0. + // Lane 1 will be contain 0. + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // Append a 1 byte to the end of the last block only if it is a + // full 16 byte block. + CMPBNE R3, $16, 2(PC) + VLEIB $4, $1, M_4 + + // We have previously saved r and 5r in the 32-bit even indexes + // of the R_[0-4] and R5_[1-4] coefficient registers. + // + // We want lane 0 to be multiplied by r so we need to move the + // saved r value into the 32-bit odd index in lane 0. We want + // lane 1 to be set to the value 1. This makes multiplication + // a no-op. We do this by setting lane 1 in every register to 0 + // and then just setting the 32-bit index 3 in R_0 to 1. + VZERO T_0 + MOVD $0, R0 + MOVD $0x10111213, R12 + VLVGP R12, R0, T_1 // [_, 0x10111213, _, 0x00000000] + VPERM T_0, R_0, T_1, R_0 // [_, r₂₆[0], _, 0] + VPERM T_0, R_1, T_1, R_1 // [_, r₂₆[1], _, 0] + VPERM T_0, R_2, T_1, R_2 // [_, r₂₆[2], _, 0] + VPERM T_0, R_3, T_1, R_3 // [_, r₂₆[3], _, 0] + VPERM T_0, R_4, T_1, R_4 // [_, r₂₆[4], _, 0] + VPERM T_0, R5_1, T_1, R5_1 // [_, 5r₂₆[1], _, 0] + VPERM T_0, R5_2, T_1, R5_2 // [_, 5r₂₆[2], _, 0] + VPERM T_0, R5_3, T_1, R5_3 // [_, 5r₂₆[3], _, 0] + VPERM T_0, R5_4, T_1, R5_4 // [_, 5r₂₆[4], _, 0] + + // Set the value of lane 1 to be 1. + VLEIF $3, $1, R_0 // [_, r₂₆[0], _, 1] + + MOVD $0, R3 + BR multiply diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go new file mode 100644 index 00000000..4fad24f8 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego +// +build !purego + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +import "unsafe" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go new file mode 100644 index 00000000..80ccbed2 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go @@ -0,0 +1,36 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build purego +// +build purego + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +// This is the Google App Engine standard variant based on reflect +// because the unsafe package and cgo are disallowed. + +import "reflect" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && + reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go new file mode 100644 index 00000000..1ab07d07 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/buffer.go @@ -0,0 +1,97 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "io" + "sync" +) + +// buffer provides a linked list buffer for data exchange +// between producer and consumer. Theoretically the buffer is +// of unlimited capacity as it does no allocation of its own. +type buffer struct { + // protects concurrent access to head, tail and closed + *sync.Cond + + head *element // the buffer that will be read first + tail *element // the buffer that will be read last + + closed bool +} + +// An element represents a single link in a linked list. +type element struct { + buf []byte + next *element +} + +// newBuffer returns an empty buffer that is not closed. +func newBuffer() *buffer { + e := new(element) + b := &buffer{ + Cond: newCond(), + head: e, + tail: e, + } + return b +} + +// write makes buf available for Read to receive. +// buf must not be modified after the call to write. +func (b *buffer) write(buf []byte) { + b.Cond.L.Lock() + e := &element{buf: buf} + b.tail.next = e + b.tail = e + b.Cond.Signal() + b.Cond.L.Unlock() +} + +// eof closes the buffer. Reads from the buffer once all +// the data has been consumed will receive io.EOF. +func (b *buffer) eof() { + b.Cond.L.Lock() + b.closed = true + b.Cond.Signal() + b.Cond.L.Unlock() +} + +// Read reads data from the internal buffer in buf. Reads will block +// if no data is available, or until the buffer is closed. +func (b *buffer) Read(buf []byte) (n int, err error) { + b.Cond.L.Lock() + defer b.Cond.L.Unlock() + + for len(buf) > 0 { + // if there is data in b.head, copy it + if len(b.head.buf) > 0 { + r := copy(buf, b.head.buf) + buf, b.head.buf = buf[r:], b.head.buf[r:] + n += r + continue + } + // if there is a next buffer, make it the head + if len(b.head.buf) == 0 && b.head != b.tail { + b.head = b.head.next + continue + } + + // if at least one byte has been copied, return + if n > 0 { + break + } + + // if nothing was read, and there is nothing outstanding + // check to see if the buffer is closed. + if b.closed { + err = io.EOF + break + } + // out of buffers, wait for producer + b.Cond.Wait() + } + return +} diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go new file mode 100644 index 00000000..4600c207 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -0,0 +1,589 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "sort" + "time" +) + +// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear +// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. +// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't +// appear in the Signature.Format field. +const ( + CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" + CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" + CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" + CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" + CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" + CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" + CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" + CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" + + // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a + // Certificate.Type (or PublicKey.Type), but only in + // ClientConfig.HostKeyAlgorithms. + CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com" + CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com" +) + +const ( + // Deprecated: use CertAlgoRSAv01. + CertSigAlgoRSAv01 = CertAlgoRSAv01 + // Deprecated: use CertAlgoRSASHA256v01. + CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01 + // Deprecated: use CertAlgoRSASHA512v01. + CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01 +) + +// Certificate types distinguish between host and user +// certificates. The values can be set in the CertType field of +// Certificate. +const ( + UserCert = 1 + HostCert = 2 +) + +// Signature represents a cryptographic signature. +type Signature struct { + Format string + Blob []byte + Rest []byte `ssh:"rest"` +} + +// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that +// a certificate does not expire. +const CertTimeInfinity = 1<<64 - 1 + +// An Certificate represents an OpenSSH certificate as defined in +// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the +// PublicKey interface, so it can be unmarshaled using +// ParsePublicKey. +type Certificate struct { + Nonce []byte + Key PublicKey + Serial uint64 + CertType uint32 + KeyId string + ValidPrincipals []string + ValidAfter uint64 + ValidBefore uint64 + Permissions + Reserved []byte + SignatureKey PublicKey + Signature *Signature +} + +// genericCertData holds the key-independent part of the certificate data. +// Overall, certificates contain an nonce, public key fields and +// key-independent fields. +type genericCertData struct { + Serial uint64 + CertType uint32 + KeyId string + ValidPrincipals []byte + ValidAfter uint64 + ValidBefore uint64 + CriticalOptions []byte + Extensions []byte + Reserved []byte + SignatureKey []byte + Signature []byte +} + +func marshalStringList(namelist []string) []byte { + var to []byte + for _, name := range namelist { + s := struct{ N string }{name} + to = append(to, Marshal(&s)...) + } + return to +} + +type optionsTuple struct { + Key string + Value []byte +} + +type optionsTupleValue struct { + Value string +} + +// serialize a map of critical options or extensions +// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, +// we need two length prefixes for a non-empty string value +func marshalTuples(tups map[string]string) []byte { + keys := make([]string, 0, len(tups)) + for key := range tups { + keys = append(keys, key) + } + sort.Strings(keys) + + var ret []byte + for _, key := range keys { + s := optionsTuple{Key: key} + if value := tups[key]; len(value) > 0 { + s.Value = Marshal(&optionsTupleValue{value}) + } + ret = append(ret, Marshal(&s)...) + } + return ret +} + +// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, +// we need two length prefixes for a non-empty option value +func parseTuples(in []byte) (map[string]string, error) { + tups := map[string]string{} + var lastKey string + var haveLastKey bool + + for len(in) > 0 { + var key, val, extra []byte + var ok bool + + if key, in, ok = parseString(in); !ok { + return nil, errShortRead + } + keyStr := string(key) + // according to [PROTOCOL.certkeys], the names must be in + // lexical order. + if haveLastKey && keyStr <= lastKey { + return nil, fmt.Errorf("ssh: certificate options are not in lexical order") + } + lastKey, haveLastKey = keyStr, true + // the next field is a data field, which if non-empty has a string embedded + if val, in, ok = parseString(in); !ok { + return nil, errShortRead + } + if len(val) > 0 { + val, extra, ok = parseString(val) + if !ok { + return nil, errShortRead + } + if len(extra) > 0 { + return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") + } + tups[keyStr] = string(val) + } else { + tups[keyStr] = "" + } + } + return tups, nil +} + +func parseCert(in []byte, privAlgo string) (*Certificate, error) { + nonce, rest, ok := parseString(in) + if !ok { + return nil, errShortRead + } + + key, rest, err := parsePubKey(rest, privAlgo) + if err != nil { + return nil, err + } + + var g genericCertData + if err := Unmarshal(rest, &g); err != nil { + return nil, err + } + + c := &Certificate{ + Nonce: nonce, + Key: key, + Serial: g.Serial, + CertType: g.CertType, + KeyId: g.KeyId, + ValidAfter: g.ValidAfter, + ValidBefore: g.ValidBefore, + } + + for principals := g.ValidPrincipals; len(principals) > 0; { + principal, rest, ok := parseString(principals) + if !ok { + return nil, errShortRead + } + c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) + principals = rest + } + + c.CriticalOptions, err = parseTuples(g.CriticalOptions) + if err != nil { + return nil, err + } + c.Extensions, err = parseTuples(g.Extensions) + if err != nil { + return nil, err + } + c.Reserved = g.Reserved + k, err := ParsePublicKey(g.SignatureKey) + if err != nil { + return nil, err + } + + c.SignatureKey = k + c.Signature, rest, ok = parseSignatureBody(g.Signature) + if !ok || len(rest) > 0 { + return nil, errors.New("ssh: signature parse error") + } + + return c, nil +} + +type openSSHCertSigner struct { + pub *Certificate + signer Signer +} + +type algorithmOpenSSHCertSigner struct { + *openSSHCertSigner + algorithmSigner AlgorithmSigner +} + +// NewCertSigner returns a Signer that signs with the given Certificate, whose +// private key is held by signer. It returns an error if the public key in cert +// doesn't match the key used by signer. +func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { + if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + return nil, errors.New("ssh: signer and cert have different public key") + } + + if algorithmSigner, ok := signer.(AlgorithmSigner); ok { + return &algorithmOpenSSHCertSigner{ + &openSSHCertSigner{cert, signer}, algorithmSigner}, nil + } else { + return &openSSHCertSigner{cert, signer}, nil + } +} + +func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + return s.signer.Sign(rand, data) +} + +func (s *openSSHCertSigner) PublicKey() PublicKey { + return s.pub +} + +func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm) +} + +const sourceAddressCriticalOption = "source-address" + +// CertChecker does the work of verifying a certificate. Its methods +// can be plugged into ClientConfig.HostKeyCallback and +// ServerConfig.PublicKeyCallback. For the CertChecker to work, +// minimally, the IsAuthority callback should be set. +type CertChecker struct { + // SupportedCriticalOptions lists the CriticalOptions that the + // server application layer understands. These are only used + // for user certificates. + SupportedCriticalOptions []string + + // IsUserAuthority should return true if the key is recognized as an + // authority for the given user certificate. This allows for + // certificates to be signed by other certificates. This must be set + // if this CertChecker will be checking user certificates. + IsUserAuthority func(auth PublicKey) bool + + // IsHostAuthority should report whether the key is recognized as + // an authority for this host. This allows for certificates to be + // signed by other keys, and for those other keys to only be valid + // signers for particular hostnames. This must be set if this + // CertChecker will be checking host certificates. + IsHostAuthority func(auth PublicKey, address string) bool + + // Clock is used for verifying time stamps. If nil, time.Now + // is used. + Clock func() time.Time + + // UserKeyFallback is called when CertChecker.Authenticate encounters a + // public key that is not a certificate. It must implement validation + // of user keys or else, if nil, all such keys are rejected. + UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // HostKeyFallback is called when CertChecker.CheckHostKey encounters a + // public key that is not a certificate. It must implement host key + // validation or else, if nil, all such keys are rejected. + HostKeyFallback HostKeyCallback + + // IsRevoked is called for each certificate so that revocation checking + // can be implemented. It should return true if the given certificate + // is revoked and false otherwise. If nil, no certificates are + // considered to have been revoked. + IsRevoked func(cert *Certificate) bool +} + +// CheckHostKey checks a host key certificate. This method can be +// plugged into ClientConfig.HostKeyCallback. +func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { + cert, ok := key.(*Certificate) + if !ok { + if c.HostKeyFallback != nil { + return c.HostKeyFallback(addr, remote, key) + } + return errors.New("ssh: non-certificate host key") + } + if cert.CertType != HostCert { + return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) + } + if !c.IsHostAuthority(cert.SignatureKey, addr) { + return fmt.Errorf("ssh: no authorities for hostname: %v", addr) + } + + hostname, _, err := net.SplitHostPort(addr) + if err != nil { + return err + } + + // Pass hostname only as principal for host certificates (consistent with OpenSSH) + return c.CheckCert(hostname, cert) +} + +// Authenticate checks a user certificate. Authenticate can be used as +// a value for ServerConfig.PublicKeyCallback. +func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { + cert, ok := pubKey.(*Certificate) + if !ok { + if c.UserKeyFallback != nil { + return c.UserKeyFallback(conn, pubKey) + } + return nil, errors.New("ssh: normal key pairs not accepted") + } + + if cert.CertType != UserCert { + return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) + } + if !c.IsUserAuthority(cert.SignatureKey) { + return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") + } + + if err := c.CheckCert(conn.User(), cert); err != nil { + return nil, err + } + + return &cert.Permissions, nil +} + +// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and +// the signature of the certificate. +func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { + if c.IsRevoked != nil && c.IsRevoked(cert) { + return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) + } + + for opt := range cert.CriticalOptions { + // sourceAddressCriticalOption will be enforced by + // serverAuthenticate + if opt == sourceAddressCriticalOption { + continue + } + + found := false + for _, supp := range c.SupportedCriticalOptions { + if supp == opt { + found = true + break + } + } + if !found { + return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) + } + } + + if len(cert.ValidPrincipals) > 0 { + // By default, certs are valid for all users/hosts. + found := false + for _, p := range cert.ValidPrincipals { + if p == principal { + found = true + break + } + } + if !found { + return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) + } + } + + clock := c.Clock + if clock == nil { + clock = time.Now + } + + unixNow := clock().Unix() + if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { + return fmt.Errorf("ssh: cert is not yet valid") + } + if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { + return fmt.Errorf("ssh: cert has expired") + } + if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { + return fmt.Errorf("ssh: certificate signature does not verify") + } + + return nil +} + +// SignCert signs the certificate with an authority, setting the Nonce, +// SignatureKey, and Signature fields. +func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { + c.Nonce = make([]byte, 32) + if _, err := io.ReadFull(rand, c.Nonce); err != nil { + return err + } + c.SignatureKey = authority.PublicKey() + + // Default to KeyAlgoRSASHA512 for ssh-rsa signers. + if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { + sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512) + if err != nil { + return err + } + c.Signature = sig + return nil + } + + sig, err := authority.Sign(rand, c.bytesForSigning()) + if err != nil { + return err + } + c.Signature = sig + return nil +} + +// certKeyAlgoNames is a mapping from known certificate algorithm names to the +// corresponding public key signature algorithm. +// +// This map must be kept in sync with the one in agent/client.go. +var certKeyAlgoNames = map[string]string{ + CertAlgoRSAv01: KeyAlgoRSA, + CertAlgoRSASHA256v01: KeyAlgoRSASHA256, + CertAlgoRSASHA512v01: KeyAlgoRSASHA512, + CertAlgoDSAv01: KeyAlgoDSA, + CertAlgoECDSA256v01: KeyAlgoECDSA256, + CertAlgoECDSA384v01: KeyAlgoECDSA384, + CertAlgoECDSA521v01: KeyAlgoECDSA521, + CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, + CertAlgoED25519v01: KeyAlgoED25519, + CertAlgoSKED25519v01: KeyAlgoSKED25519, +} + +// underlyingAlgo returns the signature algorithm associated with algo (which is +// an advertised or negotiated public key or host key algorithm). These are +// usually the same, except for certificate algorithms. +func underlyingAlgo(algo string) string { + if a, ok := certKeyAlgoNames[algo]; ok { + return a + } + return algo +} + +// certificateAlgo returns the certificate algorithms that uses the provided +// underlying signature algorithm. +func certificateAlgo(algo string) (certAlgo string, ok bool) { + for certName, algoName := range certKeyAlgoNames { + if algoName == algo { + return certName, true + } + } + return "", false +} + +func (cert *Certificate) bytesForSigning() []byte { + c2 := *cert + c2.Signature = nil + out := c2.Marshal() + // Drop trailing signature length. + return out[:len(out)-4] +} + +// Marshal serializes c into OpenSSH's wire format. It is part of the +// PublicKey interface. +func (c *Certificate) Marshal() []byte { + generic := genericCertData{ + Serial: c.Serial, + CertType: c.CertType, + KeyId: c.KeyId, + ValidPrincipals: marshalStringList(c.ValidPrincipals), + ValidAfter: uint64(c.ValidAfter), + ValidBefore: uint64(c.ValidBefore), + CriticalOptions: marshalTuples(c.CriticalOptions), + Extensions: marshalTuples(c.Extensions), + Reserved: c.Reserved, + SignatureKey: c.SignatureKey.Marshal(), + } + if c.Signature != nil { + generic.Signature = Marshal(c.Signature) + } + genericBytes := Marshal(&generic) + keyBytes := c.Key.Marshal() + _, keyBytes, _ = parseString(keyBytes) + prefix := Marshal(&struct { + Name string + Nonce []byte + Key []byte `ssh:"rest"` + }{c.Type(), c.Nonce, keyBytes}) + + result := make([]byte, 0, len(prefix)+len(genericBytes)) + result = append(result, prefix...) + result = append(result, genericBytes...) + return result +} + +// Type returns the certificate algorithm name. It is part of the PublicKey interface. +func (c *Certificate) Type() string { + certName, ok := certificateAlgo(c.Key.Type()) + if !ok { + panic("unknown certificate type for key type " + c.Key.Type()) + } + return certName +} + +// Verify verifies a signature against the certificate's public +// key. It is part of the PublicKey interface. +func (c *Certificate) Verify(data []byte, sig *Signature) error { + return c.Key.Verify(data, sig) +} + +func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { + format, in, ok := parseString(in) + if !ok { + return + } + + out = &Signature{ + Format: string(format), + } + + if out.Blob, in, ok = parseString(in); !ok { + return + } + + switch out.Format { + case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01: + out.Rest = in + return out, nil, ok + } + + return out, in, ok +} + +func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { + sigBytes, rest, ok := parseString(in) + if !ok { + return + } + + out, trailing, ok := parseSignatureBody(sigBytes) + if !ok || len(trailing) > 0 { + return nil, nil, false + } + return +} diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go new file mode 100644 index 00000000..c0834c00 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/channel.go @@ -0,0 +1,633 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "log" + "sync" +) + +const ( + minPacketLength = 9 + // channelMaxPacket contains the maximum number of bytes that will be + // sent in a single packet. As per RFC 4253, section 6.1, 32k is also + // the minimum. + channelMaxPacket = 1 << 15 + // We follow OpenSSH here. + channelWindowSize = 64 * channelMaxPacket +) + +// NewChannel represents an incoming request to a channel. It must either be +// accepted for use by calling Accept, or rejected by calling Reject. +type NewChannel interface { + // Accept accepts the channel creation request. It returns the Channel + // and a Go channel containing SSH requests. The Go channel must be + // serviced otherwise the Channel will hang. + Accept() (Channel, <-chan *Request, error) + + // Reject rejects the channel creation request. After calling + // this, no other methods on the Channel may be called. + Reject(reason RejectionReason, message string) error + + // ChannelType returns the type of the channel, as supplied by the + // client. + ChannelType() string + + // ExtraData returns the arbitrary payload for this channel, as supplied + // by the client. This data is specific to the channel type. + ExtraData() []byte +} + +// A Channel is an ordered, reliable, flow-controlled, duplex stream +// that is multiplexed over an SSH connection. +type Channel interface { + // Read reads up to len(data) bytes from the channel. + Read(data []byte) (int, error) + + // Write writes len(data) bytes to the channel. + Write(data []byte) (int, error) + + // Close signals end of channel use. No data may be sent after this + // call. + Close() error + + // CloseWrite signals the end of sending in-band + // data. Requests may still be sent, and the other side may + // still send data + CloseWrite() error + + // SendRequest sends a channel request. If wantReply is true, + // it will wait for a reply and return the result as a + // boolean, otherwise the return value will be false. Channel + // requests are out-of-band messages so they may be sent even + // if the data stream is closed or blocked by flow control. + // If the channel is closed before a reply is returned, io.EOF + // is returned. + SendRequest(name string, wantReply bool, payload []byte) (bool, error) + + // Stderr returns an io.ReadWriter that writes to this channel + // with the extended data type set to stderr. Stderr may + // safely be read and written from a different goroutine than + // Read and Write respectively. + Stderr() io.ReadWriter +} + +// Request is a request sent outside of the normal stream of +// data. Requests can either be specific to an SSH channel, or they +// can be global. +type Request struct { + Type string + WantReply bool + Payload []byte + + ch *channel + mux *mux +} + +// Reply sends a response to a request. It must be called for all requests +// where WantReply is true and is a no-op otherwise. The payload argument is +// ignored for replies to channel-specific requests. +func (r *Request) Reply(ok bool, payload []byte) error { + if !r.WantReply { + return nil + } + + if r.ch == nil { + return r.mux.ackRequest(ok, payload) + } + + return r.ch.ackRequest(ok) +} + +// RejectionReason is an enumeration used when rejecting channel creation +// requests. See RFC 4254, section 5.1. +type RejectionReason uint32 + +const ( + Prohibited RejectionReason = iota + 1 + ConnectionFailed + UnknownChannelType + ResourceShortage +) + +// String converts the rejection reason to human readable form. +func (r RejectionReason) String() string { + switch r { + case Prohibited: + return "administratively prohibited" + case ConnectionFailed: + return "connect failed" + case UnknownChannelType: + return "unknown channel type" + case ResourceShortage: + return "resource shortage" + } + return fmt.Sprintf("unknown reason %d", int(r)) +} + +func min(a uint32, b int) uint32 { + if a < uint32(b) { + return a + } + return uint32(b) +} + +type channelDirection uint8 + +const ( + channelInbound channelDirection = iota + channelOutbound +) + +// channel is an implementation of the Channel interface that works +// with the mux class. +type channel struct { + // R/O after creation + chanType string + extraData []byte + localId, remoteId uint32 + + // maxIncomingPayload and maxRemotePayload are the maximum + // payload sizes of normal and extended data packets for + // receiving and sending, respectively. The wire packet will + // be 9 or 13 bytes larger (excluding encryption overhead). + maxIncomingPayload uint32 + maxRemotePayload uint32 + + mux *mux + + // decided is set to true if an accept or reject message has been sent + // (for outbound channels) or received (for inbound channels). + decided bool + + // direction contains either channelOutbound, for channels created + // locally, or channelInbound, for channels created by the peer. + direction channelDirection + + // Pending internal channel messages. + msg chan interface{} + + // Since requests have no ID, there can be only one request + // with WantReply=true outstanding. This lock is held by a + // goroutine that has such an outgoing request pending. + sentRequestMu sync.Mutex + + incomingRequests chan *Request + + sentEOF bool + + // thread-safe data + remoteWin window + pending *buffer + extPending *buffer + + // windowMu protects myWindow, the flow-control window. + windowMu sync.Mutex + myWindow uint32 + + // writeMu serializes calls to mux.conn.writePacket() and + // protects sentClose and packetPool. This mutex must be + // different from windowMu, as writePacket can block if there + // is a key exchange pending. + writeMu sync.Mutex + sentClose bool + + // packetPool has a buffer for each extended channel ID to + // save allocations during writes. + packetPool map[uint32][]byte +} + +// writePacket sends a packet. If the packet is a channel close, it updates +// sentClose. This method takes the lock c.writeMu. +func (ch *channel) writePacket(packet []byte) error { + ch.writeMu.Lock() + if ch.sentClose { + ch.writeMu.Unlock() + return io.EOF + } + ch.sentClose = (packet[0] == msgChannelClose) + err := ch.mux.conn.writePacket(packet) + ch.writeMu.Unlock() + return err +} + +func (ch *channel) sendMessage(msg interface{}) error { + if debugMux { + log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg) + } + + p := Marshal(msg) + binary.BigEndian.PutUint32(p[1:], ch.remoteId) + return ch.writePacket(p) +} + +// WriteExtended writes data to a specific extended stream. These streams are +// used, for example, for stderr. +func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { + if ch.sentEOF { + return 0, io.EOF + } + // 1 byte message type, 4 bytes remoteId, 4 bytes data length + opCode := byte(msgChannelData) + headerLength := uint32(9) + if extendedCode > 0 { + headerLength += 4 + opCode = msgChannelExtendedData + } + + ch.writeMu.Lock() + packet := ch.packetPool[extendedCode] + // We don't remove the buffer from packetPool, so + // WriteExtended calls from different goroutines will be + // flagged as errors by the race detector. + ch.writeMu.Unlock() + + for len(data) > 0 { + space := min(ch.maxRemotePayload, len(data)) + if space, err = ch.remoteWin.reserve(space); err != nil { + return n, err + } + if want := headerLength + space; uint32(cap(packet)) < want { + packet = make([]byte, want) + } else { + packet = packet[:want] + } + + todo := data[:space] + + packet[0] = opCode + binary.BigEndian.PutUint32(packet[1:], ch.remoteId) + if extendedCode > 0 { + binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode)) + } + binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo))) + copy(packet[headerLength:], todo) + if err = ch.writePacket(packet); err != nil { + return n, err + } + + n += len(todo) + data = data[len(todo):] + } + + ch.writeMu.Lock() + ch.packetPool[extendedCode] = packet + ch.writeMu.Unlock() + + return n, err +} + +func (ch *channel) handleData(packet []byte) error { + headerLen := 9 + isExtendedData := packet[0] == msgChannelExtendedData + if isExtendedData { + headerLen = 13 + } + if len(packet) < headerLen { + // malformed data packet + return parseError(packet[0]) + } + + var extended uint32 + if isExtendedData { + extended = binary.BigEndian.Uint32(packet[5:]) + } + + length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen]) + if length == 0 { + return nil + } + if length > ch.maxIncomingPayload { + // TODO(hanwen): should send Disconnect? + return errors.New("ssh: incoming packet exceeds maximum payload size") + } + + data := packet[headerLen:] + if length != uint32(len(data)) { + return errors.New("ssh: wrong packet length") + } + + ch.windowMu.Lock() + if ch.myWindow < length { + ch.windowMu.Unlock() + // TODO(hanwen): should send Disconnect with reason? + return errors.New("ssh: remote side wrote too much") + } + ch.myWindow -= length + ch.windowMu.Unlock() + + if extended == 1 { + ch.extPending.write(data) + } else if extended > 0 { + // discard other extended data. + } else { + ch.pending.write(data) + } + return nil +} + +func (c *channel) adjustWindow(n uint32) error { + c.windowMu.Lock() + // Since myWindow is managed on our side, and can never exceed + // the initial window setting, we don't worry about overflow. + c.myWindow += uint32(n) + c.windowMu.Unlock() + return c.sendMessage(windowAdjustMsg{ + AdditionalBytes: uint32(n), + }) +} + +func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) { + switch extended { + case 1: + n, err = c.extPending.Read(data) + case 0: + n, err = c.pending.Read(data) + default: + return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended) + } + + if n > 0 { + err = c.adjustWindow(uint32(n)) + // sendWindowAdjust can return io.EOF if the remote + // peer has closed the connection, however we want to + // defer forwarding io.EOF to the caller of Read until + // the buffer has been drained. + if n > 0 && err == io.EOF { + err = nil + } + } + + return n, err +} + +func (c *channel) close() { + c.pending.eof() + c.extPending.eof() + close(c.msg) + close(c.incomingRequests) + c.writeMu.Lock() + // This is not necessary for a normal channel teardown, but if + // there was another error, it is. + c.sentClose = true + c.writeMu.Unlock() + // Unblock writers. + c.remoteWin.close() +} + +// responseMessageReceived is called when a success or failure message is +// received on a channel to check that such a message is reasonable for the +// given channel. +func (ch *channel) responseMessageReceived() error { + if ch.direction == channelInbound { + return errors.New("ssh: channel response message received on inbound channel") + } + if ch.decided { + return errors.New("ssh: duplicate response received for channel") + } + ch.decided = true + return nil +} + +func (ch *channel) handlePacket(packet []byte) error { + switch packet[0] { + case msgChannelData, msgChannelExtendedData: + return ch.handleData(packet) + case msgChannelClose: + ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId}) + ch.mux.chanList.remove(ch.localId) + ch.close() + return nil + case msgChannelEOF: + // RFC 4254 is mute on how EOF affects dataExt messages but + // it is logical to signal EOF at the same time. + ch.extPending.eof() + ch.pending.eof() + return nil + } + + decoded, err := decode(packet) + if err != nil { + return err + } + + switch msg := decoded.(type) { + case *channelOpenFailureMsg: + if err := ch.responseMessageReceived(); err != nil { + return err + } + ch.mux.chanList.remove(msg.PeersID) + ch.msg <- msg + case *channelOpenConfirmMsg: + if err := ch.responseMessageReceived(); err != nil { + return err + } + if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { + return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize) + } + ch.remoteId = msg.MyID + ch.maxRemotePayload = msg.MaxPacketSize + ch.remoteWin.add(msg.MyWindow) + ch.msg <- msg + case *windowAdjustMsg: + if !ch.remoteWin.add(msg.AdditionalBytes) { + return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes) + } + case *channelRequestMsg: + req := Request{ + Type: msg.Request, + WantReply: msg.WantReply, + Payload: msg.RequestSpecificData, + ch: ch, + } + + ch.incomingRequests <- &req + default: + ch.msg <- msg + } + return nil +} + +func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { + ch := &channel{ + remoteWin: window{Cond: newCond()}, + myWindow: channelWindowSize, + pending: newBuffer(), + extPending: newBuffer(), + direction: direction, + incomingRequests: make(chan *Request, chanSize), + msg: make(chan interface{}, chanSize), + chanType: chanType, + extraData: extraData, + mux: m, + packetPool: make(map[uint32][]byte), + } + ch.localId = m.chanList.add(ch) + return ch +} + +var errUndecided = errors.New("ssh: must Accept or Reject channel") +var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") + +type extChannel struct { + code uint32 + ch *channel +} + +func (e *extChannel) Write(data []byte) (n int, err error) { + return e.ch.WriteExtended(data, e.code) +} + +func (e *extChannel) Read(data []byte) (n int, err error) { + return e.ch.ReadExtended(data, e.code) +} + +func (ch *channel) Accept() (Channel, <-chan *Request, error) { + if ch.decided { + return nil, nil, errDecidedAlready + } + ch.maxIncomingPayload = channelMaxPacket + confirm := channelOpenConfirmMsg{ + PeersID: ch.remoteId, + MyID: ch.localId, + MyWindow: ch.myWindow, + MaxPacketSize: ch.maxIncomingPayload, + } + ch.decided = true + if err := ch.sendMessage(confirm); err != nil { + return nil, nil, err + } + + return ch, ch.incomingRequests, nil +} + +func (ch *channel) Reject(reason RejectionReason, message string) error { + if ch.decided { + return errDecidedAlready + } + reject := channelOpenFailureMsg{ + PeersID: ch.remoteId, + Reason: reason, + Message: message, + Language: "en", + } + ch.decided = true + return ch.sendMessage(reject) +} + +func (ch *channel) Read(data []byte) (int, error) { + if !ch.decided { + return 0, errUndecided + } + return ch.ReadExtended(data, 0) +} + +func (ch *channel) Write(data []byte) (int, error) { + if !ch.decided { + return 0, errUndecided + } + return ch.WriteExtended(data, 0) +} + +func (ch *channel) CloseWrite() error { + if !ch.decided { + return errUndecided + } + ch.sentEOF = true + return ch.sendMessage(channelEOFMsg{ + PeersID: ch.remoteId}) +} + +func (ch *channel) Close() error { + if !ch.decided { + return errUndecided + } + + return ch.sendMessage(channelCloseMsg{ + PeersID: ch.remoteId}) +} + +// Extended returns an io.ReadWriter that sends and receives data on the given, +// SSH extended stream. Such streams are used, for example, for stderr. +func (ch *channel) Extended(code uint32) io.ReadWriter { + if !ch.decided { + return nil + } + return &extChannel{code, ch} +} + +func (ch *channel) Stderr() io.ReadWriter { + return ch.Extended(1) +} + +func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { + if !ch.decided { + return false, errUndecided + } + + if wantReply { + ch.sentRequestMu.Lock() + defer ch.sentRequestMu.Unlock() + } + + msg := channelRequestMsg{ + PeersID: ch.remoteId, + Request: name, + WantReply: wantReply, + RequestSpecificData: payload, + } + + if err := ch.sendMessage(msg); err != nil { + return false, err + } + + if wantReply { + m, ok := (<-ch.msg) + if !ok { + return false, io.EOF + } + switch m.(type) { + case *channelRequestFailureMsg: + return false, nil + case *channelRequestSuccessMsg: + return true, nil + default: + return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m) + } + } + + return false, nil +} + +// ackRequest either sends an ack or nack to the channel request. +func (ch *channel) ackRequest(ok bool) error { + if !ch.decided { + return errUndecided + } + + var msg interface{} + if !ok { + msg = channelRequestFailureMsg{ + PeersID: ch.remoteId, + } + } else { + msg = channelRequestSuccessMsg{ + PeersID: ch.remoteId, + } + } + return ch.sendMessage(msg) +} + +func (ch *channel) ChannelType() string { + return ch.chanType +} + +func (ch *channel) ExtraData() []byte { + return ch.extraData +} diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go new file mode 100644 index 00000000..770e8a66 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -0,0 +1,789 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/rc4" + "crypto/subtle" + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "io/ioutil" + + "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/poly1305" +) + +const ( + packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. + + // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations + // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC + // indicates implementations SHOULD be able to handle larger packet sizes, but then + // waffles on about reasonable limits. + // + // OpenSSH caps their maxPacket at 256kB so we choose to do + // the same. maxPacket is also used to ensure that uint32 + // length fields do not overflow, so it should remain well + // below 4G. + maxPacket = 256 * 1024 +) + +// noneCipher implements cipher.Stream and provides no encryption. It is used +// by the transport before the first key-exchange. +type noneCipher struct{} + +func (c noneCipher) XORKeyStream(dst, src []byte) { + copy(dst, src) +} + +func newAESCTR(key, iv []byte) (cipher.Stream, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + return cipher.NewCTR(c, iv), nil +} + +func newRC4(key, iv []byte) (cipher.Stream, error) { + return rc4.NewCipher(key) +} + +type cipherMode struct { + keySize int + ivSize int + create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) +} + +func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + stream, err := createFunc(key, iv) + if err != nil { + return nil, err + } + + var streamDump []byte + if skip > 0 { + streamDump = make([]byte, 512) + } + + for remainingToDump := skip; remainingToDump > 0; { + dumpThisTime := remainingToDump + if dumpThisTime > len(streamDump) { + dumpThisTime = len(streamDump) + } + stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) + remainingToDump -= dumpThisTime + } + + mac := macModes[algs.MAC].new(macKey) + return &streamPacketCipher{ + mac: mac, + etm: macModes[algs.MAC].etm, + macResult: make([]byte, mac.Size()), + cipher: stream, + }, nil + } +} + +// cipherModes documents properties of supported ciphers. Ciphers not included +// are not supported and will not be negotiated, even if explicitly requested in +// ClientConfig.Crypto.Ciphers. +var cipherModes = map[string]*cipherMode{ + // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms + // are defined in the order specified in the RFC. + "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + + // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. + // They are defined in the order specified in the RFC. + "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, + "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, + + // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. + // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and + // RC4) has problems with weak keys, and should be used with caution." + // RFC4345 introduces improved versions of Arcfour. + "arcfour": {16, 0, streamCipherMode(0, newRC4)}, + + // AEAD ciphers + gcmCipherID: {16, 12, newGCMCipher}, + chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, + + // CBC mode is insecure and so is not included in the default config. + // (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely + // needed, it's possible to specify a custom Config to enable it. + // You should expect that an active attacker can recover plaintext if + // you do. + aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, + + // 3des-cbc is insecure and is not included in the default + // config. + tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, +} + +// prefixLen is the length of the packet prefix that contains the packet length +// and number of padding bytes. +const prefixLen = 5 + +// streamPacketCipher is a packetCipher using a stream cipher. +type streamPacketCipher struct { + mac hash.Hash + cipher cipher.Stream + etm bool + + // The following members are to avoid per-packet allocations. + prefix [prefixLen]byte + seqNumBytes [4]byte + padding [2 * packetSizeMultiple]byte + packetData []byte + macResult []byte +} + +// readCipherPacket reads and decrypt a single packet from the reader argument. +func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { + if _, err := io.ReadFull(r, s.prefix[:]); err != nil { + return nil, err + } + + var encryptedPaddingLength [1]byte + if s.mac != nil && s.etm { + copy(encryptedPaddingLength[:], s.prefix[4:5]) + s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) + } else { + s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) + } + + length := binary.BigEndian.Uint32(s.prefix[0:4]) + paddingLength := uint32(s.prefix[4]) + + var macSize uint32 + if s.mac != nil { + s.mac.Reset() + binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) + s.mac.Write(s.seqNumBytes[:]) + if s.etm { + s.mac.Write(s.prefix[:4]) + s.mac.Write(encryptedPaddingLength[:]) + } else { + s.mac.Write(s.prefix[:]) + } + macSize = uint32(s.mac.Size()) + } + + if length <= paddingLength+1 { + return nil, errors.New("ssh: invalid packet length, packet too small") + } + + if length > maxPacket { + return nil, errors.New("ssh: invalid packet length, packet too large") + } + + // the maxPacket check above ensures that length-1+macSize + // does not overflow. + if uint32(cap(s.packetData)) < length-1+macSize { + s.packetData = make([]byte, length-1+macSize) + } else { + s.packetData = s.packetData[:length-1+macSize] + } + + if _, err := io.ReadFull(r, s.packetData); err != nil { + return nil, err + } + mac := s.packetData[length-1:] + data := s.packetData[:length-1] + + if s.mac != nil && s.etm { + s.mac.Write(data) + } + + s.cipher.XORKeyStream(data, data) + + if s.mac != nil { + if !s.etm { + s.mac.Write(data) + } + s.macResult = s.mac.Sum(s.macResult[:0]) + if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { + return nil, errors.New("ssh: MAC failure") + } + } + + return s.packetData[:length-paddingLength-1], nil +} + +// writeCipherPacket encrypts and sends a packet of data to the writer argument +func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + if len(packet) > maxPacket { + return errors.New("ssh: packet too large") + } + + aadlen := 0 + if s.mac != nil && s.etm { + // packet length is not encrypted for EtM modes + aadlen = 4 + } + + paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple + if paddingLength < 4 { + paddingLength += packetSizeMultiple + } + + length := len(packet) + 1 + paddingLength + binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) + s.prefix[4] = byte(paddingLength) + padding := s.padding[:paddingLength] + if _, err := io.ReadFull(rand, padding); err != nil { + return err + } + + if s.mac != nil { + s.mac.Reset() + binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) + s.mac.Write(s.seqNumBytes[:]) + + if s.etm { + // For EtM algorithms, the packet length must stay unencrypted, + // but the following data (padding length) must be encrypted + s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) + } + + s.mac.Write(s.prefix[:]) + + if !s.etm { + // For non-EtM algorithms, the algorithm is applied on unencrypted data + s.mac.Write(packet) + s.mac.Write(padding) + } + } + + if !(s.mac != nil && s.etm) { + // For EtM algorithms, the padding length has already been encrypted + // and the packet length must remain unencrypted + s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) + } + + s.cipher.XORKeyStream(packet, packet) + s.cipher.XORKeyStream(padding, padding) + + if s.mac != nil && s.etm { + // For EtM algorithms, packet and padding must be encrypted + s.mac.Write(packet) + s.mac.Write(padding) + } + + if _, err := w.Write(s.prefix[:]); err != nil { + return err + } + if _, err := w.Write(packet); err != nil { + return err + } + if _, err := w.Write(padding); err != nil { + return err + } + + if s.mac != nil { + s.macResult = s.mac.Sum(s.macResult[:0]) + if _, err := w.Write(s.macResult); err != nil { + return err + } + } + + return nil +} + +type gcmCipher struct { + aead cipher.AEAD + prefix [4]byte + iv []byte + buf []byte +} + +func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + aead, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + return &gcmCipher{ + aead: aead, + iv: iv, + }, nil +} + +const gcmTagSize = 16 + +func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + // Pad out to multiple of 16 bytes. This is different from the + // stream cipher because that encrypts the length too. + padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) + if padding < 4 { + padding += packetSizeMultiple + } + + length := uint32(len(packet) + int(padding) + 1) + binary.BigEndian.PutUint32(c.prefix[:], length) + if _, err := w.Write(c.prefix[:]); err != nil { + return err + } + + if cap(c.buf) < int(length) { + c.buf = make([]byte, length) + } else { + c.buf = c.buf[:length] + } + + c.buf[0] = padding + copy(c.buf[1:], packet) + if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { + return err + } + c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) + if _, err := w.Write(c.buf); err != nil { + return err + } + c.incIV() + + return nil +} + +func (c *gcmCipher) incIV() { + for i := 4 + 7; i >= 4; i-- { + c.iv[i]++ + if c.iv[i] != 0 { + break + } + } +} + +func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { + if _, err := io.ReadFull(r, c.prefix[:]); err != nil { + return nil, err + } + length := binary.BigEndian.Uint32(c.prefix[:]) + if length > maxPacket { + return nil, errors.New("ssh: max packet length exceeded") + } + + if cap(c.buf) < int(length+gcmTagSize) { + c.buf = make([]byte, length+gcmTagSize) + } else { + c.buf = c.buf[:length+gcmTagSize] + } + + if _, err := io.ReadFull(r, c.buf); err != nil { + return nil, err + } + + plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) + if err != nil { + return nil, err + } + c.incIV() + + if len(plain) == 0 { + return nil, errors.New("ssh: empty packet") + } + + padding := plain[0] + if padding < 4 { + // padding is a byte, so it automatically satisfies + // the maximum size, which is 255. + return nil, fmt.Errorf("ssh: illegal padding %d", padding) + } + + if int(padding+1) >= len(plain) { + return nil, fmt.Errorf("ssh: padding %d too large", padding) + } + plain = plain[1 : length-uint32(padding)] + return plain, nil +} + +// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 +type cbcCipher struct { + mac hash.Hash + macSize uint32 + decrypter cipher.BlockMode + encrypter cipher.BlockMode + + // The following members are to avoid per-packet allocations. + seqNumBytes [4]byte + packetData []byte + macResult []byte + + // Amount of data we should still read to hide which + // verification error triggered. + oracleCamouflage uint32 +} + +func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + cbc := &cbcCipher{ + mac: macModes[algs.MAC].new(macKey), + decrypter: cipher.NewCBCDecrypter(c, iv), + encrypter: cipher.NewCBCEncrypter(c, iv), + packetData: make([]byte, 1024), + } + if cbc.mac != nil { + cbc.macSize = uint32(cbc.mac.Size()) + } + + return cbc, nil +} + +func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + cbc, err := newCBCCipher(c, key, iv, macKey, algs) + if err != nil { + return nil, err + } + + return cbc, nil +} + +func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + c, err := des.NewTripleDESCipher(key) + if err != nil { + return nil, err + } + + cbc, err := newCBCCipher(c, key, iv, macKey, algs) + if err != nil { + return nil, err + } + + return cbc, nil +} + +func maxUInt32(a, b int) uint32 { + if a > b { + return uint32(a) + } + return uint32(b) +} + +const ( + cbcMinPacketSizeMultiple = 8 + cbcMinPacketSize = 16 + cbcMinPaddingSize = 4 +) + +// cbcError represents a verification error that may leak information. +type cbcError string + +func (e cbcError) Error() string { return string(e) } + +func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { + p, err := c.readCipherPacketLeaky(seqNum, r) + if err != nil { + if _, ok := err.(cbcError); ok { + // Verification error: read a fixed amount of + // data, to make distinguishing between + // failing MAC and failing length check more + // difficult. + io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage)) + } + } + return p, err +} + +func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { + blockSize := c.decrypter.BlockSize() + + // Read the header, which will include some of the subsequent data in the + // case of block ciphers - this is copied back to the payload later. + // How many bytes of payload/padding will be read with this first read. + firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) + firstBlock := c.packetData[:firstBlockLength] + if _, err := io.ReadFull(r, firstBlock); err != nil { + return nil, err + } + + c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength + + c.decrypter.CryptBlocks(firstBlock, firstBlock) + length := binary.BigEndian.Uint32(firstBlock[:4]) + if length > maxPacket { + return nil, cbcError("ssh: packet too large") + } + if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { + // The minimum size of a packet is 16 (or the cipher block size, whichever + // is larger) bytes. + return nil, cbcError("ssh: packet too small") + } + // The length of the packet (including the length field but not the MAC) must + // be a multiple of the block size or 8, whichever is larger. + if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { + return nil, cbcError("ssh: invalid packet length multiple") + } + + paddingLength := uint32(firstBlock[4]) + if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { + return nil, cbcError("ssh: invalid packet length") + } + + // Positions within the c.packetData buffer: + macStart := 4 + length + paddingStart := macStart - paddingLength + + // Entire packet size, starting before length, ending at end of mac. + entirePacketSize := macStart + c.macSize + + // Ensure c.packetData is large enough for the entire packet data. + if uint32(cap(c.packetData)) < entirePacketSize { + // Still need to upsize and copy, but this should be rare at runtime, only + // on upsizing the packetData buffer. + c.packetData = make([]byte, entirePacketSize) + copy(c.packetData, firstBlock) + } else { + c.packetData = c.packetData[:entirePacketSize] + } + + n, err := io.ReadFull(r, c.packetData[firstBlockLength:]) + if err != nil { + return nil, err + } + c.oracleCamouflage -= uint32(n) + + remainingCrypted := c.packetData[firstBlockLength:macStart] + c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) + + mac := c.packetData[macStart:] + if c.mac != nil { + c.mac.Reset() + binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) + c.mac.Write(c.seqNumBytes[:]) + c.mac.Write(c.packetData[:macStart]) + c.macResult = c.mac.Sum(c.macResult[:0]) + if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { + return nil, cbcError("ssh: MAC failure") + } + } + + return c.packetData[prefixLen:paddingStart], nil +} + +func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) + + // Length of encrypted portion of the packet (header, payload, padding). + // Enforce minimum padding and packet size. + encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) + // Enforce block size. + encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize + + length := encLength - 4 + paddingLength := int(length) - (1 + len(packet)) + + // Overall buffer contains: header, payload, padding, mac. + // Space for the MAC is reserved in the capacity but not the slice length. + bufferSize := encLength + c.macSize + if uint32(cap(c.packetData)) < bufferSize { + c.packetData = make([]byte, encLength, bufferSize) + } else { + c.packetData = c.packetData[:encLength] + } + + p := c.packetData + + // Packet header. + binary.BigEndian.PutUint32(p, length) + p = p[4:] + p[0] = byte(paddingLength) + + // Payload. + p = p[1:] + copy(p, packet) + + // Padding. + p = p[len(packet):] + if _, err := io.ReadFull(rand, p); err != nil { + return err + } + + if c.mac != nil { + c.mac.Reset() + binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) + c.mac.Write(c.seqNumBytes[:]) + c.mac.Write(c.packetData) + // The MAC is now appended into the capacity reserved for it earlier. + c.packetData = c.mac.Sum(c.packetData) + } + + c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) + + if _, err := w.Write(c.packetData); err != nil { + return err + } + + return nil +} + +const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" + +// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com +// AEAD, which is described here: +// +// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 +// +// the methods here also implement padding, which RFC4253 Section 6 +// also requires of stream ciphers. +type chacha20Poly1305Cipher struct { + lengthKey [32]byte + contentKey [32]byte + buf []byte +} + +func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { + if len(key) != 64 { + panic(len(key)) + } + + c := &chacha20Poly1305Cipher{ + buf: make([]byte, 256), + } + + copy(c.contentKey[:], key[:32]) + copy(c.lengthKey[:], key[32:]) + return c, nil +} + +func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { + nonce := make([]byte, 12) + binary.BigEndian.PutUint32(nonce[8:], seqNum) + s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) + if err != nil { + return nil, err + } + var polyKey, discardBuf [32]byte + s.XORKeyStream(polyKey[:], polyKey[:]) + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes + + encryptedLength := c.buf[:4] + if _, err := io.ReadFull(r, encryptedLength); err != nil { + return nil, err + } + + var lenBytes [4]byte + ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) + if err != nil { + return nil, err + } + ls.XORKeyStream(lenBytes[:], encryptedLength) + + length := binary.BigEndian.Uint32(lenBytes[:]) + if length > maxPacket { + return nil, errors.New("ssh: invalid packet length, packet too large") + } + + contentEnd := 4 + length + packetEnd := contentEnd + poly1305.TagSize + if uint32(cap(c.buf)) < packetEnd { + c.buf = make([]byte, packetEnd) + copy(c.buf[:], encryptedLength) + } else { + c.buf = c.buf[:packetEnd] + } + + if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { + return nil, err + } + + var mac [poly1305.TagSize]byte + copy(mac[:], c.buf[contentEnd:packetEnd]) + if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { + return nil, errors.New("ssh: MAC failure") + } + + plain := c.buf[4:contentEnd] + s.XORKeyStream(plain, plain) + + if len(plain) == 0 { + return nil, errors.New("ssh: empty packet") + } + + padding := plain[0] + if padding < 4 { + // padding is a byte, so it automatically satisfies + // the maximum size, which is 255. + return nil, fmt.Errorf("ssh: illegal padding %d", padding) + } + + if int(padding)+1 >= len(plain) { + return nil, fmt.Errorf("ssh: padding %d too large", padding) + } + + plain = plain[1 : len(plain)-int(padding)] + + return plain, nil +} + +func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { + nonce := make([]byte, 12) + binary.BigEndian.PutUint32(nonce[8:], seqNum) + s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) + if err != nil { + return err + } + var polyKey, discardBuf [32]byte + s.XORKeyStream(polyKey[:], polyKey[:]) + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes + + // There is no blocksize, so fall back to multiple of 8 byte + // padding, as described in RFC 4253, Sec 6. + const packetSizeMultiple = 8 + + padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple + if padding < 4 { + padding += packetSizeMultiple + } + + // size (4 bytes), padding (1), payload, padding, tag. + totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize + if cap(c.buf) < totalLength { + c.buf = make([]byte, totalLength) + } else { + c.buf = c.buf[:totalLength] + } + + binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) + ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) + if err != nil { + return err + } + ls.XORKeyStream(c.buf, c.buf[:4]) + c.buf[4] = byte(padding) + copy(c.buf[5:], payload) + packetEnd := 5 + len(payload) + padding + if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil { + return err + } + + s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd]) + + var mac [poly1305.TagSize]byte + poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) + + copy(c.buf[packetEnd:], mac[:]) + + if _, err := w.Write(c.buf); err != nil { + return err + } + return nil +} diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go new file mode 100644 index 00000000..bdc356cb --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client.go @@ -0,0 +1,282 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "net" + "os" + "sync" + "time" +) + +// Client implements a traditional SSH client that supports shells, +// subprocesses, TCP port/streamlocal forwarding and tunneled dialing. +type Client struct { + Conn + + handleForwardsOnce sync.Once // guards calling (*Client).handleForwards + + forwards forwardList // forwarded tcpip connections from the remote side + mu sync.Mutex + channelHandlers map[string]chan NewChannel +} + +// HandleChannelOpen returns a channel on which NewChannel requests +// for the given type are sent. If the type already is being handled, +// nil is returned. The channel is closed when the connection is closed. +func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { + c.mu.Lock() + defer c.mu.Unlock() + if c.channelHandlers == nil { + // The SSH channel has been closed. + c := make(chan NewChannel) + close(c) + return c + } + + ch := c.channelHandlers[channelType] + if ch != nil { + return nil + } + + ch = make(chan NewChannel, chanSize) + c.channelHandlers[channelType] = ch + return ch +} + +// NewClient creates a Client on top of the given connection. +func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { + conn := &Client{ + Conn: c, + channelHandlers: make(map[string]chan NewChannel, 1), + } + + go conn.handleGlobalRequests(reqs) + go conn.handleChannelOpens(chans) + go func() { + conn.Wait() + conn.forwards.closeAll() + }() + return conn +} + +// NewClientConn establishes an authenticated SSH connection using c +// as the underlying transport. The Request and NewChannel channels +// must be serviced or the connection will hang. +func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { + fullConf := *config + fullConf.SetDefaults() + if fullConf.HostKeyCallback == nil { + c.Close() + return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback") + } + + conn := &connection{ + sshConn: sshConn{conn: c, user: fullConf.User}, + } + + if err := conn.clientHandshake(addr, &fullConf); err != nil { + c.Close() + return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) + } + conn.mux = newMux(conn.transport) + return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil +} + +// clientHandshake performs the client side key exchange. See RFC 4253 Section +// 7. +func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { + if config.ClientVersion != "" { + c.clientVersion = []byte(config.ClientVersion) + } else { + c.clientVersion = []byte(packageVersion) + } + var err error + c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) + if err != nil { + return err + } + + c.transport = newClientTransport( + newTransport(c.sshConn.conn, config.Rand, true /* is client */), + c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) + if err := c.transport.waitSession(); err != nil { + return err + } + + c.sessionID = c.transport.getSessionID() + return c.clientAuthenticate(config) +} + +// verifyHostKeySignature verifies the host key obtained in the key exchange. +// algo is the negotiated algorithm, and may be a certificate type. +func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error { + sig, rest, ok := parseSignatureBody(result.Signature) + if len(rest) > 0 || !ok { + return errors.New("ssh: signature parse error") + } + + if a := underlyingAlgo(algo); sig.Format != a { + return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a) + } + + return hostKey.Verify(result.H, sig) +} + +// NewSession opens a new Session for this client. (A session is a remote +// execution of a program.) +func (c *Client) NewSession() (*Session, error) { + ch, in, err := c.OpenChannel("session", nil) + if err != nil { + return nil, err + } + return newSession(ch, in) +} + +func (c *Client) handleGlobalRequests(incoming <-chan *Request) { + for r := range incoming { + // This handles keepalive messages and matches + // the behaviour of OpenSSH. + r.Reply(false, nil) + } +} + +// handleChannelOpens channel open messages from the remote side. +func (c *Client) handleChannelOpens(in <-chan NewChannel) { + for ch := range in { + c.mu.Lock() + handler := c.channelHandlers[ch.ChannelType()] + c.mu.Unlock() + + if handler != nil { + handler <- ch + } else { + ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) + } + } + + c.mu.Lock() + for _, ch := range c.channelHandlers { + close(ch) + } + c.channelHandlers = nil + c.mu.Unlock() +} + +// Dial starts a client connection to the given SSH server. It is a +// convenience function that connects to the given network address, +// initiates the SSH handshake, and then sets up a Client. For access +// to incoming channels and requests, use net.Dial with NewClientConn +// instead. +func Dial(network, addr string, config *ClientConfig) (*Client, error) { + conn, err := net.DialTimeout(network, addr, config.Timeout) + if err != nil { + return nil, err + } + c, chans, reqs, err := NewClientConn(conn, addr, config) + if err != nil { + return nil, err + } + return NewClient(c, chans, reqs), nil +} + +// HostKeyCallback is the function type used for verifying server +// keys. A HostKeyCallback must return nil if the host key is OK, or +// an error to reject it. It receives the hostname as passed to Dial +// or NewClientConn. The remote address is the RemoteAddr of the +// net.Conn underlying the SSH connection. +type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error + +// BannerCallback is the function type used for treat the banner sent by +// the server. A BannerCallback receives the message sent by the remote server. +type BannerCallback func(message string) error + +// A ClientConfig structure is used to configure a Client. It must not be +// modified after having been passed to an SSH function. +type ClientConfig struct { + // Config contains configuration that is shared between clients and + // servers. + Config + + // User contains the username to authenticate as. + User string + + // Auth contains possible authentication methods to use with the + // server. Only the first instance of a particular RFC 4252 method will + // be used during authentication. + Auth []AuthMethod + + // HostKeyCallback is called during the cryptographic + // handshake to validate the server's host key. The client + // configuration must supply this callback for the connection + // to succeed. The functions InsecureIgnoreHostKey or + // FixedHostKey can be used for simplistic host key checks. + HostKeyCallback HostKeyCallback + + // BannerCallback is called during the SSH dance to display a custom + // server's message. The client configuration can supply this callback to + // handle it as wished. The function BannerDisplayStderr can be used for + // simplistic display on Stderr. + BannerCallback BannerCallback + + // ClientVersion contains the version identification string that will + // be used for the connection. If empty, a reasonable default is used. + ClientVersion string + + // HostKeyAlgorithms lists the public key algorithms that the client will + // accept from the server for host key authentication, in order of + // preference. If empty, a reasonable default is used. Any + // string returned from a PublicKey.Type method may be used, or + // any of the CertAlgo and KeyAlgo constants. + HostKeyAlgorithms []string + + // Timeout is the maximum amount of time for the TCP connection to establish. + // + // A Timeout of zero means no timeout. + Timeout time.Duration +} + +// InsecureIgnoreHostKey returns a function that can be used for +// ClientConfig.HostKeyCallback to accept any host key. It should +// not be used for production code. +func InsecureIgnoreHostKey() HostKeyCallback { + return func(hostname string, remote net.Addr, key PublicKey) error { + return nil + } +} + +type fixedHostKey struct { + key PublicKey +} + +func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error { + if f.key == nil { + return fmt.Errorf("ssh: required host key was nil") + } + if !bytes.Equal(key.Marshal(), f.key.Marshal()) { + return fmt.Errorf("ssh: host key mismatch") + } + return nil +} + +// FixedHostKey returns a function for use in +// ClientConfig.HostKeyCallback to accept only a specific host key. +func FixedHostKey(key PublicKey) HostKeyCallback { + hk := &fixedHostKey{key} + return hk.check +} + +// BannerDisplayStderr returns a function that can be used for +// ClientConfig.BannerCallback to display banners on os.Stderr. +func BannerDisplayStderr() BannerCallback { + return func(banner string) error { + _, err := os.Stderr.WriteString(banner) + + return err + } +} diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go new file mode 100644 index 00000000..409b5ea1 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -0,0 +1,725 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "strings" +) + +type authResult int + +const ( + authFailure authResult = iota + authPartialSuccess + authSuccess +) + +// clientAuthenticate authenticates with the remote server. See RFC 4252. +func (c *connection) clientAuthenticate(config *ClientConfig) error { + // initiate user auth session + if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { + return err + } + packet, err := c.transport.readPacket() + if err != nil { + return err + } + // The server may choose to send a SSH_MSG_EXT_INFO at this point (if we + // advertised willingness to receive one, which we always do) or not. See + // RFC 8308, Section 2.4. + extensions := make(map[string][]byte) + if len(packet) > 0 && packet[0] == msgExtInfo { + var extInfo extInfoMsg + if err := Unmarshal(packet, &extInfo); err != nil { + return err + } + payload := extInfo.Payload + for i := uint32(0); i < extInfo.NumExtensions; i++ { + name, rest, ok := parseString(payload) + if !ok { + return parseError(msgExtInfo) + } + value, rest, ok := parseString(rest) + if !ok { + return parseError(msgExtInfo) + } + extensions[string(name)] = value + payload = rest + } + packet, err = c.transport.readPacket() + if err != nil { + return err + } + } + var serviceAccept serviceAcceptMsg + if err := Unmarshal(packet, &serviceAccept); err != nil { + return err + } + + // during the authentication phase the client first attempts the "none" method + // then any untried methods suggested by the server. + var tried []string + var lastMethods []string + + sessionID := c.transport.getSessionID() + for auth := AuthMethod(new(noneAuth)); auth != nil; { + ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions) + if err != nil { + return err + } + if ok == authSuccess { + // success + return nil + } else if ok == authFailure { + if m := auth.method(); !contains(tried, m) { + tried = append(tried, m) + } + } + if methods == nil { + methods = lastMethods + } + lastMethods = methods + + auth = nil + + findNext: + for _, a := range config.Auth { + candidateMethod := a.method() + if contains(tried, candidateMethod) { + continue + } + for _, meth := range methods { + if meth == candidateMethod { + auth = a + break findNext + } + } + } + } + return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried) +} + +func contains(list []string, e string) bool { + for _, s := range list { + if s == e { + return true + } + } + return false +} + +// An AuthMethod represents an instance of an RFC 4252 authentication method. +type AuthMethod interface { + // auth authenticates user over transport t. + // Returns true if authentication is successful. + // If authentication is not successful, a []string of alternative + // method names is returned. If the slice is nil, it will be ignored + // and the previous set of possible methods will be reused. + auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) + + // method returns the RFC 4252 method name. + method() string +} + +// "none" authentication, RFC 4252 section 5.2. +type noneAuth int + +func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { + if err := c.writePacket(Marshal(&userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: "none", + })); err != nil { + return authFailure, nil, err + } + + return handleAuthResponse(c) +} + +func (n *noneAuth) method() string { + return "none" +} + +// passwordCallback is an AuthMethod that fetches the password through +// a function call, e.g. by prompting the user. +type passwordCallback func() (password string, err error) + +func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { + type passwordAuthMsg struct { + User string `sshtype:"50"` + Service string + Method string + Reply bool + Password string + } + + pw, err := cb() + // REVIEW NOTE: is there a need to support skipping a password attempt? + // The program may only find out that the user doesn't have a password + // when prompting. + if err != nil { + return authFailure, nil, err + } + + if err := c.writePacket(Marshal(&passwordAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + Reply: false, + Password: pw, + })); err != nil { + return authFailure, nil, err + } + + return handleAuthResponse(c) +} + +func (cb passwordCallback) method() string { + return "password" +} + +// Password returns an AuthMethod using the given password. +func Password(secret string) AuthMethod { + return passwordCallback(func() (string, error) { return secret, nil }) +} + +// PasswordCallback returns an AuthMethod that uses a callback for +// fetching a password. +func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { + return passwordCallback(prompt) +} + +type publickeyAuthMsg struct { + User string `sshtype:"50"` + Service string + Method string + // HasSig indicates to the receiver packet that the auth request is signed and + // should be used for authentication of the request. + HasSig bool + Algoname string + PubKey []byte + // Sig is tagged with "rest" so Marshal will exclude it during + // validateKey + Sig []byte `ssh:"rest"` +} + +// publicKeyCallback is an AuthMethod that uses a set of key +// pairs for authentication. +type publicKeyCallback func() ([]Signer, error) + +func (cb publicKeyCallback) method() string { + return "publickey" +} + +func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) { + keyFormat := signer.PublicKey().Type() + + // Like in sendKexInit, if the public key implements AlgorithmSigner we + // assume it supports all algorithms, otherwise only the key format one. + as, ok := signer.(AlgorithmSigner) + if !ok { + return algorithmSignerWrapper{signer}, keyFormat + } + + extPayload, ok := extensions["server-sig-algs"] + if !ok { + // If there is no "server-sig-algs" extension, fall back to the key + // format algorithm. + return as, keyFormat + } + + // The server-sig-algs extension only carries underlying signature + // algorithm, but we are trying to select a protocol-level public key + // algorithm, which might be a certificate type. Extend the list of server + // supported algorithms to include the corresponding certificate algorithms. + serverAlgos := strings.Split(string(extPayload), ",") + for _, algo := range serverAlgos { + if certAlgo, ok := certificateAlgo(algo); ok { + serverAlgos = append(serverAlgos, certAlgo) + } + } + + keyAlgos := algorithmsForKeyFormat(keyFormat) + algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos) + if err != nil { + // If there is no overlap, try the key anyway with the key format + // algorithm, to support servers that fail to list all supported + // algorithms. + return as, keyFormat + } + return as, algo +} + +func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { + // Authentication is performed by sending an enquiry to test if a key is + // acceptable to the remote. If the key is acceptable, the client will + // attempt to authenticate with the valid key. If not the client will repeat + // the process with the remaining keys. + + signers, err := cb() + if err != nil { + return authFailure, nil, err + } + var methods []string + for _, signer := range signers { + pub := signer.PublicKey() + as, algo := pickSignatureAlgorithm(signer, extensions) + + ok, err := validateKey(pub, algo, user, c) + if err != nil { + return authFailure, nil, err + } + if !ok { + continue + } + + pubKey := pub.Marshal() + data := buildDataSignedForAuth(session, userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + }, algo, pubKey) + sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) + if err != nil { + return authFailure, nil, err + } + + // manually wrap the serialized signature in a string + s := Marshal(sign) + sig := make([]byte, stringLength(len(s))) + marshalString(sig, s) + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + HasSig: true, + Algoname: algo, + PubKey: pubKey, + Sig: sig, + } + p := Marshal(&msg) + if err := c.writePacket(p); err != nil { + return authFailure, nil, err + } + var success authResult + success, methods, err = handleAuthResponse(c) + if err != nil { + return authFailure, nil, err + } + + // If authentication succeeds or the list of available methods does not + // contain the "publickey" method, do not attempt to authenticate with any + // other keys. According to RFC 4252 Section 7, the latter can occur when + // additional authentication methods are required. + if success == authSuccess || !containsMethod(methods, cb.method()) { + return success, methods, err + } + } + + return authFailure, methods, nil +} + +func containsMethod(methods []string, method string) bool { + for _, m := range methods { + if m == method { + return true + } + } + + return false +} + +// validateKey validates the key provided is acceptable to the server. +func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) { + pubKey := key.Marshal() + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: "publickey", + HasSig: false, + Algoname: algo, + PubKey: pubKey, + } + if err := c.writePacket(Marshal(&msg)); err != nil { + return false, err + } + + return confirmKeyAck(key, algo, c) +} + +func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) { + pubKey := key.Marshal() + + for { + packet, err := c.readPacket() + if err != nil { + return false, err + } + switch packet[0] { + case msgUserAuthBanner: + if err := handleBannerResponse(c, packet); err != nil { + return false, err + } + case msgUserAuthPubKeyOk: + var msg userAuthPubKeyOkMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, err + } + if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) { + return false, nil + } + return true, nil + case msgUserAuthFailure: + return false, nil + default: + return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0]) + } + } +} + +// PublicKeys returns an AuthMethod that uses the given key +// pairs. +func PublicKeys(signers ...Signer) AuthMethod { + return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) +} + +// PublicKeysCallback returns an AuthMethod that runs the given +// function to obtain a list of key pairs. +func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { + return publicKeyCallback(getSigners) +} + +// handleAuthResponse returns whether the preceding authentication request succeeded +// along with a list of remaining authentication methods to try next and +// an error if an unexpected response was received. +func handleAuthResponse(c packetConn) (authResult, []string, error) { + gotMsgExtInfo := false + for { + packet, err := c.readPacket() + if err != nil { + return authFailure, nil, err + } + + switch packet[0] { + case msgUserAuthBanner: + if err := handleBannerResponse(c, packet); err != nil { + return authFailure, nil, err + } + case msgExtInfo: + // Ignore post-authentication RFC 8308 extensions, once. + if gotMsgExtInfo { + return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + gotMsgExtInfo = true + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return authFailure, nil, err + } + if msg.PartialSuccess { + return authPartialSuccess, msg.Methods, nil + } + return authFailure, msg.Methods, nil + case msgUserAuthSuccess: + return authSuccess, nil, nil + default: + return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + } +} + +func handleBannerResponse(c packetConn, packet []byte) error { + var msg userAuthBannerMsg + if err := Unmarshal(packet, &msg); err != nil { + return err + } + + transport, ok := c.(*handshakeTransport) + if !ok { + return nil + } + + if transport.bannerCallback != nil { + return transport.bannerCallback(msg.Message) + } + + return nil +} + +// KeyboardInteractiveChallenge should print questions, optionally +// disabling echoing (e.g. for passwords), and return all the answers. +// Challenge may be called multiple times in a single session. After +// successful authentication, the server may send a challenge with no +// questions, for which the name and instruction messages should be +// printed. RFC 4256 section 3.3 details how the UI should behave for +// both CLI and GUI environments. +type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error) + +// KeyboardInteractive returns an AuthMethod using a prompt/response +// sequence controlled by the server. +func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { + return challenge +} + +func (cb KeyboardInteractiveChallenge) method() string { + return "keyboard-interactive" +} + +func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { + type initiateMsg struct { + User string `sshtype:"50"` + Service string + Method string + Language string + Submethods string + } + + if err := c.writePacket(Marshal(&initiateMsg{ + User: user, + Service: serviceSSH, + Method: "keyboard-interactive", + })); err != nil { + return authFailure, nil, err + } + + gotMsgExtInfo := false + for { + packet, err := c.readPacket() + if err != nil { + return authFailure, nil, err + } + + // like handleAuthResponse, but with less options. + switch packet[0] { + case msgUserAuthBanner: + if err := handleBannerResponse(c, packet); err != nil { + return authFailure, nil, err + } + continue + case msgExtInfo: + // Ignore post-authentication RFC 8308 extensions, once. + if gotMsgExtInfo { + return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + } + gotMsgExtInfo = true + continue + case msgUserAuthInfoRequest: + // OK + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return authFailure, nil, err + } + if msg.PartialSuccess { + return authPartialSuccess, msg.Methods, nil + } + return authFailure, msg.Methods, nil + case msgUserAuthSuccess: + return authSuccess, nil, nil + default: + return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + } + + var msg userAuthInfoRequestMsg + if err := Unmarshal(packet, &msg); err != nil { + return authFailure, nil, err + } + + // Manually unpack the prompt/echo pairs. + rest := msg.Prompts + var prompts []string + var echos []bool + for i := 0; i < int(msg.NumPrompts); i++ { + prompt, r, ok := parseString(rest) + if !ok || len(r) == 0 { + return authFailure, nil, errors.New("ssh: prompt format error") + } + prompts = append(prompts, string(prompt)) + echos = append(echos, r[0] != 0) + rest = r[1:] + } + + if len(rest) != 0 { + return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") + } + + answers, err := cb(msg.Name, msg.Instruction, prompts, echos) + if err != nil { + return authFailure, nil, err + } + + if len(answers) != len(prompts) { + return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts)) + } + responseLength := 1 + 4 + for _, a := range answers { + responseLength += stringLength(len(a)) + } + serialized := make([]byte, responseLength) + p := serialized + p[0] = msgUserAuthInfoResponse + p = p[1:] + p = marshalUint32(p, uint32(len(answers))) + for _, a := range answers { + p = marshalString(p, []byte(a)) + } + + if err := c.writePacket(serialized); err != nil { + return authFailure, nil, err + } + } +} + +type retryableAuthMethod struct { + authMethod AuthMethod + maxTries int +} + +func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) { + for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { + ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions) + if ok != authFailure || err != nil { // either success, partial success or error terminate + return ok, methods, err + } + } + return ok, methods, err +} + +func (r *retryableAuthMethod) method() string { + return r.authMethod.method() +} + +// RetryableAuthMethod is a decorator for other auth methods enabling them to +// be retried up to maxTries before considering that AuthMethod itself failed. +// If maxTries is <= 0, will retry indefinitely +// +// This is useful for interactive clients using challenge/response type +// authentication (e.g. Keyboard-Interactive, Password, etc) where the user +// could mistype their response resulting in the server issuing a +// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4 +// [keyboard-interactive]); Without this decorator, the non-retryable +// AuthMethod would be removed from future consideration, and never tried again +// (and so the user would never be able to retry their entry). +func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { + return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} +} + +// GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication. +// See RFC 4462 section 3 +// gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details. +// target is the server host you want to log in to. +func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod { + if gssAPIClient == nil { + panic("gss-api client must be not nil with enable gssapi-with-mic") + } + return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target} +} + +type gssAPIWithMICCallback struct { + gssAPIClient GSSAPIClient + target string +} + +func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { + m := &userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: g.method(), + } + // The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST. + // See RFC 4462 section 3.2. + m.Payload = appendU32(m.Payload, 1) + m.Payload = appendString(m.Payload, string(krb5OID)) + if err := c.writePacket(Marshal(m)); err != nil { + return authFailure, nil, err + } + // The server responds to the SSH_MSG_USERAUTH_REQUEST with either an + // SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or + // with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE. + // See RFC 4462 section 3.3. + // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check + // selected mech if it is valid. + packet, err := c.readPacket() + if err != nil { + return authFailure, nil, err + } + userAuthGSSAPIResp := &userAuthGSSAPIResponse{} + if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil { + return authFailure, nil, err + } + // Start the loop into the exchange token. + // See RFC 4462 section 3.4. + var token []byte + defer g.gssAPIClient.DeleteSecContext() + for { + // Initiates the establishment of a security context between the application and a remote peer. + nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false) + if err != nil { + return authFailure, nil, err + } + if len(nextToken) > 0 { + if err := c.writePacket(Marshal(&userAuthGSSAPIToken{ + Token: nextToken, + })); err != nil { + return authFailure, nil, err + } + } + if !needContinue { + break + } + packet, err = c.readPacket() + if err != nil { + return authFailure, nil, err + } + switch packet[0] { + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return authFailure, nil, err + } + if msg.PartialSuccess { + return authPartialSuccess, msg.Methods, nil + } + return authFailure, msg.Methods, nil + case msgUserAuthGSSAPIError: + userAuthGSSAPIErrorResp := &userAuthGSSAPIError{} + if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil { + return authFailure, nil, err + } + return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+ + "Major Status: %d\n"+ + "Minor Status: %d\n"+ + "Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus, + userAuthGSSAPIErrorResp.Message) + case msgUserAuthGSSAPIToken: + userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} + if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { + return authFailure, nil, err + } + token = userAuthGSSAPITokenReq.Token + } + } + // Binding Encryption Keys. + // See RFC 4462 section 3.5. + micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic") + micToken, err := g.gssAPIClient.GetMIC(micField) + if err != nil { + return authFailure, nil, err + } + if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{ + MIC: micToken, + })); err != nil { + return authFailure, nil, err + } + return handleAuthResponse(c) +} + +func (g *gssAPIWithMICCallback) method() string { + return "gssapi-with-mic" +} diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go new file mode 100644 index 00000000..2a47a61d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -0,0 +1,430 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "crypto" + "crypto/rand" + "fmt" + "io" + "math" + "sync" + + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" +) + +// These are string constants in the SSH protocol. +const ( + compressionNone = "none" + serviceUserAuth = "ssh-userauth" + serviceSSH = "ssh-connection" +) + +// supportedCiphers lists ciphers we support but might not recommend. +var supportedCiphers = []string{ + "aes128-ctr", "aes192-ctr", "aes256-ctr", + "aes128-gcm@openssh.com", + chacha20Poly1305ID, + "arcfour256", "arcfour128", "arcfour", + aes128cbcID, + tripledescbcID, +} + +// preferredCiphers specifies the default preference for ciphers. +var preferredCiphers = []string{ + "aes128-gcm@openssh.com", + chacha20Poly1305ID, + "aes128-ctr", "aes192-ctr", "aes256-ctr", +} + +// supportedKexAlgos specifies the supported key-exchange algorithms in +// preference order. +var supportedKexAlgos = []string{ + kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, + // P384 and P521 are not constant-time yet, but since we don't + // reuse ephemeral keys, using them for ECDH should be OK. + kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, + kexAlgoDH14SHA256, kexAlgoDH14SHA1, kexAlgoDH1SHA1, +} + +// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden +// for the server half. +var serverForbiddenKexAlgos = map[string]struct{}{ + kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests + kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests +} + +// preferredKexAlgos specifies the default preference for key-exchange algorithms +// in preference order. +var preferredKexAlgos = []string{ + kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, + kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, + kexAlgoDH14SHA256, kexAlgoDH14SHA1, +} + +// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods +// of authenticating servers) in preference order. +var supportedHostKeyAlgos = []string{ + CertAlgoRSASHA512v01, CertAlgoRSASHA256v01, + CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, + CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, + + KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, + KeyAlgoRSASHA512, KeyAlgoRSASHA256, + KeyAlgoRSA, KeyAlgoDSA, + + KeyAlgoED25519, +} + +// supportedMACs specifies a default set of MAC algorithms in preference order. +// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed +// because they have reached the end of their useful life. +var supportedMACs = []string{ + "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", +} + +var supportedCompressions = []string{compressionNone} + +// hashFuncs keeps the mapping of supported signature algorithms to their +// respective hashes needed for signing and verification. +var hashFuncs = map[string]crypto.Hash{ + KeyAlgoRSA: crypto.SHA1, + KeyAlgoRSASHA256: crypto.SHA256, + KeyAlgoRSASHA512: crypto.SHA512, + KeyAlgoDSA: crypto.SHA1, + KeyAlgoECDSA256: crypto.SHA256, + KeyAlgoECDSA384: crypto.SHA384, + KeyAlgoECDSA521: crypto.SHA512, + // KeyAlgoED25519 doesn't pre-hash. + KeyAlgoSKECDSA256: crypto.SHA256, + KeyAlgoSKED25519: crypto.SHA256, +} + +// algorithmsForKeyFormat returns the supported signature algorithms for a given +// public key format (PublicKey.Type), in order of preference. See RFC 8332, +// Section 2. See also the note in sendKexInit on backwards compatibility. +func algorithmsForKeyFormat(keyFormat string) []string { + switch keyFormat { + case KeyAlgoRSA: + return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA} + case CertAlgoRSAv01: + return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01} + default: + return []string{keyFormat} + } +} + +// unexpectedMessageError results when the SSH message that we received didn't +// match what we wanted. +func unexpectedMessageError(expected, got uint8) error { + return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) +} + +// parseError results from a malformed SSH message. +func parseError(tag uint8) error { + return fmt.Errorf("ssh: parse error in message type %d", tag) +} + +func findCommon(what string, client []string, server []string) (common string, err error) { + for _, c := range client { + for _, s := range server { + if c == s { + return c, nil + } + } + } + return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) +} + +// directionAlgorithms records algorithm choices in one direction (either read or write) +type directionAlgorithms struct { + Cipher string + MAC string + Compression string +} + +// rekeyBytes returns a rekeying intervals in bytes. +func (a *directionAlgorithms) rekeyBytes() int64 { + // According to RFC4344 block ciphers should rekey after + // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is + // 128. + switch a.Cipher { + case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID: + return 16 * (1 << 32) + + } + + // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data. + return 1 << 30 +} + +var aeadCiphers = map[string]bool{ + gcmCipherID: true, + chacha20Poly1305ID: true, +} + +type algorithms struct { + kex string + hostKey string + w directionAlgorithms + r directionAlgorithms +} + +func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { + result := &algorithms{} + + result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) + if err != nil { + return + } + + result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) + if err != nil { + return + } + + stoc, ctos := &result.w, &result.r + if isClient { + ctos, stoc = stoc, ctos + } + + ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) + if err != nil { + return + } + + stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) + if err != nil { + return + } + + if !aeadCiphers[ctos.Cipher] { + ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) + if err != nil { + return + } + } + + if !aeadCiphers[stoc.Cipher] { + stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) + if err != nil { + return + } + } + + ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) + if err != nil { + return + } + + stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) + if err != nil { + return + } + + return result, nil +} + +// If rekeythreshold is too small, we can't make any progress sending +// stuff. +const minRekeyThreshold uint64 = 256 + +// Config contains configuration data common to both ServerConfig and +// ClientConfig. +type Config struct { + // Rand provides the source of entropy for cryptographic + // primitives. If Rand is nil, the cryptographic random reader + // in package crypto/rand will be used. + Rand io.Reader + + // The maximum number of bytes sent or received after which a + // new key is negotiated. It must be at least 256. If + // unspecified, a size suitable for the chosen cipher is used. + RekeyThreshold uint64 + + // The allowed key exchanges algorithms. If unspecified then a + // default set of algorithms is used. + KeyExchanges []string + + // The allowed cipher algorithms. If unspecified then a sensible + // default is used. + Ciphers []string + + // The allowed MAC algorithms. If unspecified then a sensible default + // is used. + MACs []string +} + +// SetDefaults sets sensible values for unset fields in config. This is +// exported for testing: Configs passed to SSH functions are copied and have +// default values set automatically. +func (c *Config) SetDefaults() { + if c.Rand == nil { + c.Rand = rand.Reader + } + if c.Ciphers == nil { + c.Ciphers = preferredCiphers + } + var ciphers []string + for _, c := range c.Ciphers { + if cipherModes[c] != nil { + // reject the cipher if we have no cipherModes definition + ciphers = append(ciphers, c) + } + } + c.Ciphers = ciphers + + if c.KeyExchanges == nil { + c.KeyExchanges = preferredKexAlgos + } + + if c.MACs == nil { + c.MACs = supportedMACs + } + + if c.RekeyThreshold == 0 { + // cipher specific default + } else if c.RekeyThreshold < minRekeyThreshold { + c.RekeyThreshold = minRekeyThreshold + } else if c.RekeyThreshold >= math.MaxInt64 { + // Avoid weirdness if somebody uses -1 as a threshold. + c.RekeyThreshold = math.MaxInt64 + } +} + +// buildDataSignedForAuth returns the data that is signed in order to prove +// possession of a private key. See RFC 4252, section 7. algo is the advertised +// algorithm, and may be a certificate type. +func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte { + data := struct { + Session []byte + Type byte + User string + Service string + Method string + Sign bool + Algo string + PubKey []byte + }{ + sessionID, + msgUserAuthRequest, + req.User, + req.Service, + req.Method, + true, + algo, + pubKey, + } + return Marshal(data) +} + +func appendU16(buf []byte, n uint16) []byte { + return append(buf, byte(n>>8), byte(n)) +} + +func appendU32(buf []byte, n uint32) []byte { + return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) +} + +func appendU64(buf []byte, n uint64) []byte { + return append(buf, + byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), + byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) +} + +func appendInt(buf []byte, n int) []byte { + return appendU32(buf, uint32(n)) +} + +func appendString(buf []byte, s string) []byte { + buf = appendU32(buf, uint32(len(s))) + buf = append(buf, s...) + return buf +} + +func appendBool(buf []byte, b bool) []byte { + if b { + return append(buf, 1) + } + return append(buf, 0) +} + +// newCond is a helper to hide the fact that there is no usable zero +// value for sync.Cond. +func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } + +// window represents the buffer available to clients +// wishing to write to a channel. +type window struct { + *sync.Cond + win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 + writeWaiters int + closed bool +} + +// add adds win to the amount of window available +// for consumers. +func (w *window) add(win uint32) bool { + // a zero sized window adjust is a noop. + if win == 0 { + return true + } + w.L.Lock() + if w.win+win < win { + w.L.Unlock() + return false + } + w.win += win + // It is unusual that multiple goroutines would be attempting to reserve + // window space, but not guaranteed. Use broadcast to notify all waiters + // that additional window is available. + w.Broadcast() + w.L.Unlock() + return true +} + +// close sets the window to closed, so all reservations fail +// immediately. +func (w *window) close() { + w.L.Lock() + w.closed = true + w.Broadcast() + w.L.Unlock() +} + +// reserve reserves win from the available window capacity. +// If no capacity remains, reserve will block. reserve may +// return less than requested. +func (w *window) reserve(win uint32) (uint32, error) { + var err error + w.L.Lock() + w.writeWaiters++ + w.Broadcast() + for w.win == 0 && !w.closed { + w.Wait() + } + w.writeWaiters-- + if w.win < win { + win = w.win + } + w.win -= win + if w.closed { + err = io.EOF + } + w.L.Unlock() + return win, err +} + +// waitWriterBlocked waits until some goroutine is blocked for further +// writes. It is used in tests only. +func (w *window) waitWriterBlocked() { + w.Cond.L.Lock() + for w.writeWaiters == 0 { + w.Cond.Wait() + } + w.Cond.L.Unlock() +} diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go new file mode 100644 index 00000000..fd6b0681 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/connection.go @@ -0,0 +1,143 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "fmt" + "net" +) + +// OpenChannelError is returned if the other side rejects an +// OpenChannel request. +type OpenChannelError struct { + Reason RejectionReason + Message string +} + +func (e *OpenChannelError) Error() string { + return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) +} + +// ConnMetadata holds metadata for the connection. +type ConnMetadata interface { + // User returns the user ID for this connection. + User() string + + // SessionID returns the session hash, also denoted by H. + SessionID() []byte + + // ClientVersion returns the client's version string as hashed + // into the session ID. + ClientVersion() []byte + + // ServerVersion returns the server's version string as hashed + // into the session ID. + ServerVersion() []byte + + // RemoteAddr returns the remote address for this connection. + RemoteAddr() net.Addr + + // LocalAddr returns the local address for this connection. + LocalAddr() net.Addr +} + +// Conn represents an SSH connection for both server and client roles. +// Conn is the basis for implementing an application layer, such +// as ClientConn, which implements the traditional shell access for +// clients. +type Conn interface { + ConnMetadata + + // SendRequest sends a global request, and returns the + // reply. If wantReply is true, it returns the response status + // and payload. See also RFC4254, section 4. + SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) + + // OpenChannel tries to open an channel. If the request is + // rejected, it returns *OpenChannelError. On success it returns + // the SSH Channel and a Go channel for incoming, out-of-band + // requests. The Go channel must be serviced, or the + // connection will hang. + OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) + + // Close closes the underlying network connection + Close() error + + // Wait blocks until the connection has shut down, and returns the + // error causing the shutdown. + Wait() error + + // TODO(hanwen): consider exposing: + // RequestKeyChange + // Disconnect +} + +// DiscardRequests consumes and rejects all requests from the +// passed-in channel. +func DiscardRequests(in <-chan *Request) { + for req := range in { + if req.WantReply { + req.Reply(false, nil) + } + } +} + +// A connection represents an incoming connection. +type connection struct { + transport *handshakeTransport + sshConn + + // The connection protocol. + *mux +} + +func (c *connection) Close() error { + return c.sshConn.conn.Close() +} + +// sshconn provides net.Conn metadata, but disallows direct reads and +// writes. +type sshConn struct { + conn net.Conn + + user string + sessionID []byte + clientVersion []byte + serverVersion []byte +} + +func dup(src []byte) []byte { + dst := make([]byte, len(src)) + copy(dst, src) + return dst +} + +func (c *sshConn) User() string { + return c.user +} + +func (c *sshConn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +func (c *sshConn) Close() error { + return c.conn.Close() +} + +func (c *sshConn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +func (c *sshConn) SessionID() []byte { + return dup(c.sessionID) +} + +func (c *sshConn) ClientVersion() []byte { + return dup(c.clientVersion) +} + +func (c *sshConn) ServerVersion() []byte { + return dup(c.serverVersion) +} diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go new file mode 100644 index 00000000..f6bff60d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/doc.go @@ -0,0 +1,22 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package ssh implements an SSH client and server. + +SSH is a transport security protocol, an authentication protocol and a +family of application protocols. The most typical application level +protocol is a remote shell and this is specifically implemented. However, +the multiplexed nature of SSH is exposed to users that wish to support +others. + +References: + + [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD + [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 + +This package does not fall under the stability promise of the Go language itself, +so its API may be changed when pressing needs arise. +*/ +package ssh // import "golang.org/x/crypto/ssh" diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go new file mode 100644 index 00000000..653dc4d2 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -0,0 +1,704 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "crypto/rand" + "errors" + "fmt" + "io" + "log" + "net" + "sync" +) + +// debugHandshake, if set, prints messages sent and received. Key +// exchange messages are printed as if DH were used, so the debug +// messages are wrong when using ECDH. +const debugHandshake = false + +// chanSize sets the amount of buffering SSH connections. This is +// primarily for testing: setting chanSize=0 uncovers deadlocks more +// quickly. +const chanSize = 16 + +// keyingTransport is a packet based transport that supports key +// changes. It need not be thread-safe. It should pass through +// msgNewKeys in both directions. +type keyingTransport interface { + packetConn + + // prepareKeyChange sets up a key change. The key change for a + // direction will be effected if a msgNewKeys message is sent + // or received. + prepareKeyChange(*algorithms, *kexResult) error +} + +// handshakeTransport implements rekeying on top of a keyingTransport +// and offers a thread-safe writePacket() interface. +type handshakeTransport struct { + conn keyingTransport + config *Config + + serverVersion []byte + clientVersion []byte + + // hostKeys is non-empty if we are the server. In that case, + // it contains all host keys that can be used to sign the + // connection. + hostKeys []Signer + + // hostKeyAlgorithms is non-empty if we are the client. In that case, + // we accept these key types from the server as host key. + hostKeyAlgorithms []string + + // On read error, incoming is closed, and readError is set. + incoming chan []byte + readError error + + mu sync.Mutex + writeError error + sentInitPacket []byte + sentInitMsg *kexInitMsg + pendingPackets [][]byte // Used when a key exchange is in progress. + + // If the read loop wants to schedule a kex, it pings this + // channel, and the write loop will send out a kex + // message. + requestKex chan struct{} + + // If the other side requests or confirms a kex, its kexInit + // packet is sent here for the write loop to find it. + startKex chan *pendingKex + + // data for host key checking + hostKeyCallback HostKeyCallback + dialAddress string + remoteAddr net.Addr + + // bannerCallback is non-empty if we are the client and it has been set in + // ClientConfig. In that case it is called during the user authentication + // dance to handle a custom server's message. + bannerCallback BannerCallback + + // Algorithms agreed in the last key exchange. + algorithms *algorithms + + readPacketsLeft uint32 + readBytesLeft int64 + + writePacketsLeft uint32 + writeBytesLeft int64 + + // The session ID or nil if first kex did not complete yet. + sessionID []byte +} + +type pendingKex struct { + otherInit []byte + done chan error +} + +func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport { + t := &handshakeTransport{ + conn: conn, + serverVersion: serverVersion, + clientVersion: clientVersion, + incoming: make(chan []byte, chanSize), + requestKex: make(chan struct{}, 1), + startKex: make(chan *pendingKex, 1), + + config: config, + } + t.resetReadThresholds() + t.resetWriteThresholds() + + // We always start with a mandatory key exchange. + t.requestKex <- struct{}{} + return t +} + +func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport { + t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) + t.dialAddress = dialAddr + t.remoteAddr = addr + t.hostKeyCallback = config.HostKeyCallback + t.bannerCallback = config.BannerCallback + if config.HostKeyAlgorithms != nil { + t.hostKeyAlgorithms = config.HostKeyAlgorithms + } else { + t.hostKeyAlgorithms = supportedHostKeyAlgos + } + go t.readLoop() + go t.kexLoop() + return t +} + +func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { + t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) + t.hostKeys = config.hostKeys + go t.readLoop() + go t.kexLoop() + return t +} + +func (t *handshakeTransport) getSessionID() []byte { + return t.sessionID +} + +// waitSession waits for the session to be established. This should be +// the first thing to call after instantiating handshakeTransport. +func (t *handshakeTransport) waitSession() error { + p, err := t.readPacket() + if err != nil { + return err + } + if p[0] != msgNewKeys { + return fmt.Errorf("ssh: first packet should be msgNewKeys") + } + + return nil +} + +func (t *handshakeTransport) id() string { + if len(t.hostKeys) > 0 { + return "server" + } + return "client" +} + +func (t *handshakeTransport) printPacket(p []byte, write bool) { + action := "got" + if write { + action = "sent" + } + + if p[0] == msgChannelData || p[0] == msgChannelExtendedData { + log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p)) + } else { + msg, err := decode(p) + log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err) + } +} + +func (t *handshakeTransport) readPacket() ([]byte, error) { + p, ok := <-t.incoming + if !ok { + return nil, t.readError + } + return p, nil +} + +func (t *handshakeTransport) readLoop() { + first := true + for { + p, err := t.readOnePacket(first) + first = false + if err != nil { + t.readError = err + close(t.incoming) + break + } + if p[0] == msgIgnore || p[0] == msgDebug { + continue + } + t.incoming <- p + } + + // Stop writers too. + t.recordWriteError(t.readError) + + // Unblock the writer should it wait for this. + close(t.startKex) + + // Don't close t.requestKex; it's also written to from writePacket. +} + +func (t *handshakeTransport) pushPacket(p []byte) error { + if debugHandshake { + t.printPacket(p, true) + } + return t.conn.writePacket(p) +} + +func (t *handshakeTransport) getWriteError() error { + t.mu.Lock() + defer t.mu.Unlock() + return t.writeError +} + +func (t *handshakeTransport) recordWriteError(err error) { + t.mu.Lock() + defer t.mu.Unlock() + if t.writeError == nil && err != nil { + t.writeError = err + } +} + +func (t *handshakeTransport) requestKeyExchange() { + select { + case t.requestKex <- struct{}{}: + default: + // something already requested a kex, so do nothing. + } +} + +func (t *handshakeTransport) resetWriteThresholds() { + t.writePacketsLeft = packetRekeyThreshold + if t.config.RekeyThreshold > 0 { + t.writeBytesLeft = int64(t.config.RekeyThreshold) + } else if t.algorithms != nil { + t.writeBytesLeft = t.algorithms.w.rekeyBytes() + } else { + t.writeBytesLeft = 1 << 30 + } +} + +func (t *handshakeTransport) kexLoop() { + +write: + for t.getWriteError() == nil { + var request *pendingKex + var sent bool + + for request == nil || !sent { + var ok bool + select { + case request, ok = <-t.startKex: + if !ok { + break write + } + case <-t.requestKex: + break + } + + if !sent { + if err := t.sendKexInit(); err != nil { + t.recordWriteError(err) + break + } + sent = true + } + } + + if err := t.getWriteError(); err != nil { + if request != nil { + request.done <- err + } + break + } + + // We're not servicing t.requestKex, but that is OK: + // we never block on sending to t.requestKex. + + // We're not servicing t.startKex, but the remote end + // has just sent us a kexInitMsg, so it can't send + // another key change request, until we close the done + // channel on the pendingKex request. + + err := t.enterKeyExchange(request.otherInit) + + t.mu.Lock() + t.writeError = err + t.sentInitPacket = nil + t.sentInitMsg = nil + + t.resetWriteThresholds() + + // we have completed the key exchange. Since the + // reader is still blocked, it is safe to clear out + // the requestKex channel. This avoids the situation + // where: 1) we consumed our own request for the + // initial kex, and 2) the kex from the remote side + // caused another send on the requestKex channel, + clear: + for { + select { + case <-t.requestKex: + // + default: + break clear + } + } + + request.done <- t.writeError + + // kex finished. Push packets that we received while + // the kex was in progress. Don't look at t.startKex + // and don't increment writtenSinceKex: if we trigger + // another kex while we are still busy with the last + // one, things will become very confusing. + for _, p := range t.pendingPackets { + t.writeError = t.pushPacket(p) + if t.writeError != nil { + break + } + } + t.pendingPackets = t.pendingPackets[:0] + t.mu.Unlock() + } + + // drain startKex channel. We don't service t.requestKex + // because nobody does blocking sends there. + go func() { + for init := range t.startKex { + init.done <- t.writeError + } + }() + + // Unblock reader. + t.conn.Close() +} + +// The protocol uses uint32 for packet counters, so we can't let them +// reach 1<<32. We will actually read and write more packets than +// this, though: the other side may send more packets, and after we +// hit this limit on writing we will send a few more packets for the +// key exchange itself. +const packetRekeyThreshold = (1 << 31) + +func (t *handshakeTransport) resetReadThresholds() { + t.readPacketsLeft = packetRekeyThreshold + if t.config.RekeyThreshold > 0 { + t.readBytesLeft = int64(t.config.RekeyThreshold) + } else if t.algorithms != nil { + t.readBytesLeft = t.algorithms.r.rekeyBytes() + } else { + t.readBytesLeft = 1 << 30 + } +} + +func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) { + p, err := t.conn.readPacket() + if err != nil { + return nil, err + } + + if t.readPacketsLeft > 0 { + t.readPacketsLeft-- + } else { + t.requestKeyExchange() + } + + if t.readBytesLeft > 0 { + t.readBytesLeft -= int64(len(p)) + } else { + t.requestKeyExchange() + } + + if debugHandshake { + t.printPacket(p, false) + } + + if first && p[0] != msgKexInit { + return nil, fmt.Errorf("ssh: first packet should be msgKexInit") + } + + if p[0] != msgKexInit { + return p, nil + } + + firstKex := t.sessionID == nil + + kex := pendingKex{ + done: make(chan error, 1), + otherInit: p, + } + t.startKex <- &kex + err = <-kex.done + + if debugHandshake { + log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err) + } + + if err != nil { + return nil, err + } + + t.resetReadThresholds() + + // By default, a key exchange is hidden from higher layers by + // translating it into msgIgnore. + successPacket := []byte{msgIgnore} + if firstKex { + // sendKexInit() for the first kex waits for + // msgNewKeys so the authentication process is + // guaranteed to happen over an encrypted transport. + successPacket = []byte{msgNewKeys} + } + + return successPacket, nil +} + +// sendKexInit sends a key change message. +func (t *handshakeTransport) sendKexInit() error { + t.mu.Lock() + defer t.mu.Unlock() + if t.sentInitMsg != nil { + // kexInits may be sent either in response to the other side, + // or because our side wants to initiate a key change, so we + // may have already sent a kexInit. In that case, don't send a + // second kexInit. + return nil + } + + msg := &kexInitMsg{ + KexAlgos: t.config.KeyExchanges, + CiphersClientServer: t.config.Ciphers, + CiphersServerClient: t.config.Ciphers, + MACsClientServer: t.config.MACs, + MACsServerClient: t.config.MACs, + CompressionClientServer: supportedCompressions, + CompressionServerClient: supportedCompressions, + } + io.ReadFull(rand.Reader, msg.Cookie[:]) + + isServer := len(t.hostKeys) > 0 + if isServer { + for _, k := range t.hostKeys { + // If k is an AlgorithmSigner, presume it supports all signature algorithms + // associated with the key format. (Ideally AlgorithmSigner would have a + // method to advertise supported algorithms, but it doesn't. This means that + // adding support for a new algorithm is a breaking change, as we will + // immediately negotiate it even if existing implementations don't support + // it. If that ever happens, we'll have to figure something out.) + // If k is not an AlgorithmSigner, we can only assume it only supports the + // algorithms that matches the key format. (This means that Sign can't pick + // a different default.) + keyFormat := k.PublicKey().Type() + if _, ok := k.(AlgorithmSigner); ok { + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...) + } else { + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat) + } + } + } else { + msg.ServerHostKeyAlgos = t.hostKeyAlgorithms + + // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what + // algorithms the server supports for public key authentication. See RFC + // 8308, Section 2.1. + if firstKeyExchange := t.sessionID == nil; firstKeyExchange { + msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1) + msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) + msg.KexAlgos = append(msg.KexAlgos, "ext-info-c") + } + } + + packet := Marshal(msg) + + // writePacket destroys the contents, so save a copy. + packetCopy := make([]byte, len(packet)) + copy(packetCopy, packet) + + if err := t.pushPacket(packetCopy); err != nil { + return err + } + + t.sentInitMsg = msg + t.sentInitPacket = packet + + return nil +} + +func (t *handshakeTransport) writePacket(p []byte) error { + switch p[0] { + case msgKexInit: + return errors.New("ssh: only handshakeTransport can send kexInit") + case msgNewKeys: + return errors.New("ssh: only handshakeTransport can send newKeys") + } + + t.mu.Lock() + defer t.mu.Unlock() + if t.writeError != nil { + return t.writeError + } + + if t.sentInitMsg != nil { + // Copy the packet so the writer can reuse the buffer. + cp := make([]byte, len(p)) + copy(cp, p) + t.pendingPackets = append(t.pendingPackets, cp) + return nil + } + + if t.writeBytesLeft > 0 { + t.writeBytesLeft -= int64(len(p)) + } else { + t.requestKeyExchange() + } + + if t.writePacketsLeft > 0 { + t.writePacketsLeft-- + } else { + t.requestKeyExchange() + } + + if err := t.pushPacket(p); err != nil { + t.writeError = err + } + + return nil +} + +func (t *handshakeTransport) Close() error { + return t.conn.Close() +} + +func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { + if debugHandshake { + log.Printf("%s entered key exchange", t.id()) + } + + otherInit := &kexInitMsg{} + if err := Unmarshal(otherInitPacket, otherInit); err != nil { + return err + } + + magics := handshakeMagics{ + clientVersion: t.clientVersion, + serverVersion: t.serverVersion, + clientKexInit: otherInitPacket, + serverKexInit: t.sentInitPacket, + } + + clientInit := otherInit + serverInit := t.sentInitMsg + isClient := len(t.hostKeys) == 0 + if isClient { + clientInit, serverInit = serverInit, clientInit + + magics.clientKexInit = t.sentInitPacket + magics.serverKexInit = otherInitPacket + } + + var err error + t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit) + if err != nil { + return err + } + + // We don't send FirstKexFollows, but we handle receiving it. + // + // RFC 4253 section 7 defines the kex and the agreement method for + // first_kex_packet_follows. It states that the guessed packet + // should be ignored if the "kex algorithm and/or the host + // key algorithm is guessed wrong (server and client have + // different preferred algorithm), or if any of the other + // algorithms cannot be agreed upon". The other algorithms have + // already been checked above so the kex algorithm and host key + // algorithm are checked here. + if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) { + // other side sent a kex message for the wrong algorithm, + // which we have to ignore. + if _, err := t.conn.readPacket(); err != nil { + return err + } + } + + kex, ok := kexAlgoMap[t.algorithms.kex] + if !ok { + return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex) + } + + var result *kexResult + if len(t.hostKeys) > 0 { + result, err = t.server(kex, &magics) + } else { + result, err = t.client(kex, &magics) + } + + if err != nil { + return err + } + + if t.sessionID == nil { + t.sessionID = result.H + } + result.SessionID = t.sessionID + + if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil { + return err + } + if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { + return err + } + if packet, err := t.conn.readPacket(); err != nil { + return err + } else if packet[0] != msgNewKeys { + return unexpectedMessageError(msgNewKeys, packet[0]) + } + + return nil +} + +// algorithmSignerWrapper is an AlgorithmSigner that only supports the default +// key format algorithm. +// +// This is technically a violation of the AlgorithmSigner interface, but it +// should be unreachable given where we use this. Anyway, at least it returns an +// error instead of panicing or producing an incorrect signature. +type algorithmSignerWrapper struct { + Signer +} + +func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + if algorithm != underlyingAlgo(a.PublicKey().Type()) { + return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm") + } + return a.Sign(rand, data) +} + +func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner { + for _, k := range hostKeys { + if algo == k.PublicKey().Type() { + return algorithmSignerWrapper{k} + } + k, ok := k.(AlgorithmSigner) + if !ok { + continue + } + for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) { + if algo == a { + return k + } + } + } + return nil +} + +func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { + hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey) + if hostKey == nil { + return nil, errors.New("ssh: internal error: negotiated unsupported signature type") + } + + r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey) + return r, err +} + +func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { + result, err := kex.Client(t.conn, t.config.Rand, magics) + if err != nil { + return nil, err + } + + hostKey, err := ParsePublicKey(result.HostKey) + if err != nil { + return nil, err + } + + if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil { + return nil, err + } + + err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey) + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go new file mode 100644 index 00000000..af81d266 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go @@ -0,0 +1,93 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD. +// +// See https://flak.tedunangst.com/post/bcrypt-pbkdf and +// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c. +package bcrypt_pbkdf + +import ( + "crypto/sha512" + "errors" + "golang.org/x/crypto/blowfish" +) + +const blockSize = 32 + +// Key derives a key from the password, salt and rounds count, returning a +// []byte of length keyLen that can be used as cryptographic key. +func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) { + if rounds < 1 { + return nil, errors.New("bcrypt_pbkdf: number of rounds is too small") + } + if len(password) == 0 { + return nil, errors.New("bcrypt_pbkdf: empty password") + } + if len(salt) == 0 || len(salt) > 1<<20 { + return nil, errors.New("bcrypt_pbkdf: bad salt length") + } + if keyLen > 1024 { + return nil, errors.New("bcrypt_pbkdf: keyLen is too large") + } + + numBlocks := (keyLen + blockSize - 1) / blockSize + key := make([]byte, numBlocks*blockSize) + + h := sha512.New() + h.Write(password) + shapass := h.Sum(nil) + + shasalt := make([]byte, 0, sha512.Size) + cnt, tmp := make([]byte, 4), make([]byte, blockSize) + for block := 1; block <= numBlocks; block++ { + h.Reset() + h.Write(salt) + cnt[0] = byte(block >> 24) + cnt[1] = byte(block >> 16) + cnt[2] = byte(block >> 8) + cnt[3] = byte(block) + h.Write(cnt) + bcryptHash(tmp, shapass, h.Sum(shasalt)) + + out := make([]byte, blockSize) + copy(out, tmp) + for i := 2; i <= rounds; i++ { + h.Reset() + h.Write(tmp) + bcryptHash(tmp, shapass, h.Sum(shasalt)) + for j := 0; j < len(out); j++ { + out[j] ^= tmp[j] + } + } + + for i, v := range out { + key[i*numBlocks+(block-1)] = v + } + } + return key[:keyLen], nil +} + +var magic = []byte("OxychromaticBlowfishSwatDynamite") + +func bcryptHash(out, shapass, shasalt []byte) { + c, err := blowfish.NewSaltedCipher(shapass, shasalt) + if err != nil { + panic(err) + } + for i := 0; i < 64; i++ { + blowfish.ExpandKey(shasalt, c) + blowfish.ExpandKey(shapass, c) + } + copy(out, magic) + for i := 0; i < 32; i += 8 { + for j := 0; j < 64; j++ { + c.Encrypt(out[i:i+8], out[i:i+8]) + } + } + // Swap bytes due to different endianness. + for i := 0; i < 32; i += 4 { + out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3] + } +} diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go new file mode 100644 index 00000000..927a90cd --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/kex.go @@ -0,0 +1,774 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/subtle" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + + "golang.org/x/crypto/curve25519" +) + +const ( + kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" + kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" + kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256" + kexAlgoECDH256 = "ecdh-sha2-nistp256" + kexAlgoECDH384 = "ecdh-sha2-nistp384" + kexAlgoECDH521 = "ecdh-sha2-nistp521" + kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org" + kexAlgoCurve25519SHA256 = "curve25519-sha256" + + // For the following kex only the client half contains a production + // ready implementation. The server half only consists of a minimal + // implementation to satisfy the automated tests. + kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1" + kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256" +) + +// kexResult captures the outcome of a key exchange. +type kexResult struct { + // Session hash. See also RFC 4253, section 8. + H []byte + + // Shared secret. See also RFC 4253, section 8. + K []byte + + // Host key as hashed into H. + HostKey []byte + + // Signature of H. + Signature []byte + + // A cryptographic hash function that matches the security + // level of the key exchange algorithm. It is used for + // calculating H, and for deriving keys from H and K. + Hash crypto.Hash + + // The session ID, which is the first H computed. This is used + // to derive key material inside the transport. + SessionID []byte +} + +// handshakeMagics contains data that is always included in the +// session hash. +type handshakeMagics struct { + clientVersion, serverVersion []byte + clientKexInit, serverKexInit []byte +} + +func (m *handshakeMagics) write(w io.Writer) { + writeString(w, m.clientVersion) + writeString(w, m.serverVersion) + writeString(w, m.clientKexInit) + writeString(w, m.serverKexInit) +} + +// kexAlgorithm abstracts different key exchange algorithms. +type kexAlgorithm interface { + // Server runs server-side key agreement, signing the result + // with a hostkey. algo is the negotiated algorithm, and may + // be a certificate type. + Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error) + + // Client runs the client-side key agreement. Caller is + // responsible for verifying the host key signature. + Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) +} + +// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. +type dhGroup struct { + g, p, pMinus1 *big.Int + hashFunc crypto.Hash +} + +func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { + if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") + } + return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil +} + +func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { + var x *big.Int + for { + var err error + if x, err = rand.Int(randSource, group.pMinus1); err != nil { + return nil, err + } + if x.Sign() > 0 { + break + } + } + + X := new(big.Int).Exp(group.g, x, group.p) + kexDHInit := kexDHInitMsg{ + X: X, + } + if err := c.writePacket(Marshal(&kexDHInit)); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexDHReply kexDHReplyMsg + if err = Unmarshal(packet, &kexDHReply); err != nil { + return nil, err + } + + ki, err := group.diffieHellman(kexDHReply.Y, x) + if err != nil { + return nil, err + } + + h := group.hashFunc.New() + magics.write(h) + writeString(h, kexDHReply.HostKey) + writeInt(h, X) + writeInt(h, kexDHReply.Y) + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: kexDHReply.HostKey, + Signature: kexDHReply.Signature, + Hash: group.hashFunc, + }, nil +} + +func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return + } + var kexDHInit kexDHInitMsg + if err = Unmarshal(packet, &kexDHInit); err != nil { + return + } + + var y *big.Int + for { + if y, err = rand.Int(randSource, group.pMinus1); err != nil { + return + } + if y.Sign() > 0 { + break + } + } + + Y := new(big.Int).Exp(group.g, y, group.p) + ki, err := group.diffieHellman(kexDHInit.X, y) + if err != nil { + return nil, err + } + + hostKeyBytes := priv.PublicKey().Marshal() + + h := group.hashFunc.New() + magics.write(h) + writeString(h, hostKeyBytes) + writeInt(h, kexDHInit.X) + writeInt(h, Y) + + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, randSource, H, algo) + if err != nil { + return nil, err + } + + kexDHReply := kexDHReplyMsg{ + HostKey: hostKeyBytes, + Y: Y, + Signature: sig, + } + packet = Marshal(&kexDHReply) + + err = c.writePacket(packet) + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: group.hashFunc, + }, err +} + +// ecdh performs Elliptic Curve Diffie-Hellman key exchange as +// described in RFC 5656, section 4. +type ecdh struct { + curve elliptic.Curve +} + +func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + ephKey, err := ecdsa.GenerateKey(kex.curve, rand) + if err != nil { + return nil, err + } + + kexInit := kexECDHInitMsg{ + ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), + } + + serialized := Marshal(&kexInit) + if err := c.writePacket(serialized); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + + x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) + if err != nil { + return nil, err + } + + // generate shared secret + secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) + + h := ecHash(kex.curve).New() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, kexInit.ClientPubKey) + writeString(h, reply.EphemeralPubKey) + K := make([]byte, intLength(secret)) + marshalInt(K, secret) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: ecHash(kex.curve), + }, nil +} + +// unmarshalECKey parses and checks an EC key. +func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { + x, y = elliptic.Unmarshal(curve, pubkey) + if x == nil { + return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") + } + if !validateECPublicKey(curve, x, y) { + return nil, nil, errors.New("ssh: public key not on curve") + } + return x, y, nil +} + +// validateECPublicKey checks that the point is a valid public key for +// the given curve. See [SEC1], 3.2.2 +func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + + if x.Cmp(curve.Params().P) >= 0 { + return false + } + + if y.Cmp(curve.Params().P) >= 0 { + return false + } + + if !curve.IsOnCurve(x, y) { + return false + } + + // We don't check if N * PubKey == 0, since + // + // - the NIST curves have cofactor = 1, so this is implicit. + // (We don't foresee an implementation that supports non NIST + // curves) + // + // - for ephemeral keys, we don't need to worry about small + // subgroup attacks. + return true +} + +func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexECDHInit kexECDHInitMsg + if err = Unmarshal(packet, &kexECDHInit); err != nil { + return nil, err + } + + clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) + if err != nil { + return nil, err + } + + // We could cache this key across multiple users/multiple + // connection attempts, but the benefit is small. OpenSSH + // generates a new key for each incoming connection. + ephKey, err := ecdsa.GenerateKey(kex.curve, rand) + if err != nil { + return nil, err + } + + hostKeyBytes := priv.PublicKey().Marshal() + + serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) + + // generate shared secret + secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) + + h := ecHash(kex.curve).New() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexECDHInit.ClientPubKey) + writeString(h, serializedEphKey) + + K := make([]byte, intLength(secret)) + marshalInt(K, secret) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, rand, H, algo) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: serializedEphKey, + HostKey: hostKeyBytes, + Signature: sig, + } + + serialized := Marshal(&reply) + if err := c.writePacket(serialized); err != nil { + return nil, err + } + + return &kexResult{ + H: H, + K: K, + HostKey: reply.HostKey, + Signature: sig, + Hash: ecHash(kex.curve), + }, nil +} + +// ecHash returns the hash to match the given elliptic curve, see RFC +// 5656, section 6.2.1 +func ecHash(curve elliptic.Curve) crypto.Hash { + bitSize := curve.Params().BitSize + switch { + case bitSize <= 256: + return crypto.SHA256 + case bitSize <= 384: + return crypto.SHA384 + } + return crypto.SHA512 +} + +var kexAlgoMap = map[string]kexAlgorithm{} + +func init() { + // This is the group called diffie-hellman-group1-sha1 in + // RFC 4253 and Oakley Group 2 in RFC 2409. + p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) + kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + pMinus1: new(big.Int).Sub(p, bigOne), + hashFunc: crypto.SHA1, + } + + // This are the groups called diffie-hellman-group14-sha1 and + // diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268, + // and Oakley Group 14 in RFC 3526. + p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + group14 := &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + pMinus1: new(big.Int).Sub(p, bigOne), + } + + kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ + g: group14.g, p: group14.p, pMinus1: group14.pMinus1, + hashFunc: crypto.SHA1, + } + kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{ + g: group14.g, p: group14.p, pMinus1: group14.pMinus1, + hashFunc: crypto.SHA256, + } + + kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} + kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} + kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} + kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} + kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{} + kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} + kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} +} + +// curve25519sha256 implements the curve25519-sha256 (formerly known as +// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731. +type curve25519sha256 struct{} + +type curve25519KeyPair struct { + priv [32]byte + pub [32]byte +} + +func (kp *curve25519KeyPair) generate(rand io.Reader) error { + if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { + return err + } + curve25519.ScalarBaseMult(&kp.pub, &kp.priv) + return nil +} + +// curve25519Zeros is just an array of 32 zero bytes so that we have something +// convenient to compare against in order to reject curve25519 points with the +// wrong order. +var curve25519Zeros [32]byte + +func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + var kp curve25519KeyPair + if err := kp.generate(rand); err != nil { + return nil, err + } + if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + if len(reply.EphemeralPubKey) != 32 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong length") + } + + var servPub, secret [32]byte + copy(servPub[:], reply.EphemeralPubKey) + curve25519.ScalarMult(&secret, &kp.priv, &servPub) + if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + } + + h := crypto.SHA256.New() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, kp.pub[:]) + writeString(h, reply.EphemeralPubKey) + + ki := new(big.Int).SetBytes(secret[:]) + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: crypto.SHA256, + }, nil +} + +func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return + } + var kexInit kexECDHInitMsg + if err = Unmarshal(packet, &kexInit); err != nil { + return + } + + if len(kexInit.ClientPubKey) != 32 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong length") + } + + var kp curve25519KeyPair + if err := kp.generate(rand); err != nil { + return nil, err + } + + var clientPub, secret [32]byte + copy(clientPub[:], kexInit.ClientPubKey) + curve25519.ScalarMult(&secret, &kp.priv, &clientPub) + if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + } + + hostKeyBytes := priv.PublicKey().Marshal() + + h := crypto.SHA256.New() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexInit.ClientPubKey) + writeString(h, kp.pub[:]) + + ki := new(big.Int).SetBytes(secret[:]) + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + H := h.Sum(nil) + + sig, err := signAndMarshal(priv, rand, H, algo) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: kp.pub[:], + HostKey: hostKeyBytes, + Signature: sig, + } + if err := c.writePacket(Marshal(&reply)); err != nil { + return nil, err + } + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: crypto.SHA256, + }, nil +} + +// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and +// diffie-hellman-group-exchange-sha256 key agreement protocols, +// as described in RFC 4419 +type dhGEXSHA struct { + hashFunc crypto.Hash +} + +const ( + dhGroupExchangeMinimumBits = 2048 + dhGroupExchangePreferredBits = 2048 + dhGroupExchangeMaximumBits = 8192 +) + +func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { + // Send GexRequest + kexDHGexRequest := kexDHGexRequestMsg{ + MinBits: dhGroupExchangeMinimumBits, + PreferedBits: dhGroupExchangePreferredBits, + MaxBits: dhGroupExchangeMaximumBits, + } + if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil { + return nil, err + } + + // Receive GexGroup + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var msg kexDHGexGroupMsg + if err = Unmarshal(packet, &msg); err != nil { + return nil, err + } + + // reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits + if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits { + return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen()) + } + + // Check if g is safe by verifying that 1 < g < p-1 + pMinusOne := new(big.Int).Sub(msg.P, bigOne) + if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 { + return nil, fmt.Errorf("ssh: server provided gex g is not safe") + } + + // Send GexInit + pHalf := new(big.Int).Rsh(msg.P, 1) + x, err := rand.Int(randSource, pHalf) + if err != nil { + return nil, err + } + X := new(big.Int).Exp(msg.G, x, msg.P) + kexDHGexInit := kexDHGexInitMsg{ + X: X, + } + if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil { + return nil, err + } + + // Receive GexReply + packet, err = c.readPacket() + if err != nil { + return nil, err + } + + var kexDHGexReply kexDHGexReplyMsg + if err = Unmarshal(packet, &kexDHGexReply); err != nil { + return nil, err + } + + if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") + } + kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P) + + // Check if k is safe by verifying that k > 1 and k < p - 1 + if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 { + return nil, fmt.Errorf("ssh: derived k is not safe") + } + + h := gex.hashFunc.New() + magics.write(h) + writeString(h, kexDHGexReply.HostKey) + binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) + binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) + binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) + writeInt(h, msg.P) + writeInt(h, msg.G) + writeInt(h, X) + writeInt(h, kexDHGexReply.Y) + K := make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: kexDHGexReply.HostKey, + Signature: kexDHGexReply.Signature, + Hash: gex.hashFunc, + }, nil +} + +// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. +// +// This is a minimal implementation to satisfy the automated tests. +func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { + // Receive GexRequest + packet, err := c.readPacket() + if err != nil { + return + } + var kexDHGexRequest kexDHGexRequestMsg + if err = Unmarshal(packet, &kexDHGexRequest); err != nil { + return + } + + // Send GexGroup + // This is the group called diffie-hellman-group14-sha1 in RFC + // 4253 and Oakley Group 14 in RFC 3526. + p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + g := big.NewInt(2) + + msg := &kexDHGexGroupMsg{ + P: p, + G: g, + } + if err := c.writePacket(Marshal(msg)); err != nil { + return nil, err + } + + // Receive GexInit + packet, err = c.readPacket() + if err != nil { + return + } + var kexDHGexInit kexDHGexInitMsg + if err = Unmarshal(packet, &kexDHGexInit); err != nil { + return + } + + pHalf := new(big.Int).Rsh(p, 1) + + y, err := rand.Int(randSource, pHalf) + if err != nil { + return + } + Y := new(big.Int).Exp(g, y, p) + + pMinusOne := new(big.Int).Sub(p, bigOne) + if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") + } + kInt := new(big.Int).Exp(kexDHGexInit.X, y, p) + + hostKeyBytes := priv.PublicKey().Marshal() + + h := gex.hashFunc.New() + magics.write(h) + writeString(h, hostKeyBytes) + binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) + binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) + binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) + writeInt(h, p) + writeInt(h, g) + writeInt(h, kexDHGexInit.X) + writeInt(h, Y) + + K := make([]byte, intLength(kInt)) + marshalInt(K, kInt) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, randSource, H, algo) + if err != nil { + return nil, err + } + + kexDHGexReply := kexDHGexReplyMsg{ + HostKey: hostKeyBytes, + Y: Y, + Signature: sig, + } + packet = Marshal(&kexDHGexReply) + + err = c.writePacket(packet) + + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: gex.hashFunc, + }, err +} diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go new file mode 100644 index 00000000..1c7de1a6 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -0,0 +1,1447 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bytes" + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/md5" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/asn1" + "encoding/base64" + "encoding/hex" + "encoding/pem" + "errors" + "fmt" + "io" + "math/big" + "strings" + + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf" +) + +// Public key algorithms names. These values can appear in PublicKey.Type, +// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner +// arguments. +const ( + KeyAlgoRSA = "ssh-rsa" + KeyAlgoDSA = "ssh-dss" + KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" + KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" + KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" + KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" + KeyAlgoED25519 = "ssh-ed25519" + KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com" + + // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not + // public key formats, so they can't appear as a PublicKey.Type. The + // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. + KeyAlgoRSASHA256 = "rsa-sha2-256" + KeyAlgoRSASHA512 = "rsa-sha2-512" +) + +const ( + // Deprecated: use KeyAlgoRSA. + SigAlgoRSA = KeyAlgoRSA + // Deprecated: use KeyAlgoRSASHA256. + SigAlgoRSASHA2256 = KeyAlgoRSASHA256 + // Deprecated: use KeyAlgoRSASHA512. + SigAlgoRSASHA2512 = KeyAlgoRSASHA512 +) + +// parsePubKey parses a public key of the given algorithm. +// Use ParsePublicKey for keys with prepended algorithm. +func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { + switch algo { + case KeyAlgoRSA: + return parseRSA(in) + case KeyAlgoDSA: + return parseDSA(in) + case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: + return parseECDSA(in) + case KeyAlgoSKECDSA256: + return parseSKECDSA(in) + case KeyAlgoED25519: + return parseED25519(in) + case KeyAlgoSKED25519: + return parseSKEd25519(in) + case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: + cert, err := parseCert(in, certKeyAlgoNames[algo]) + if err != nil { + return nil, nil, err + } + return cert, nil, nil + } + return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo) +} + +// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format +// (see sshd(8) manual page) once the options and key type fields have been +// removed. +func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { + in = bytes.TrimSpace(in) + + i := bytes.IndexAny(in, " \t") + if i == -1 { + i = len(in) + } + base64Key := in[:i] + + key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) + n, err := base64.StdEncoding.Decode(key, base64Key) + if err != nil { + return nil, "", err + } + key = key[:n] + out, err = ParsePublicKey(key) + if err != nil { + return nil, "", err + } + comment = string(bytes.TrimSpace(in[i:])) + return out, comment, nil +} + +// ParseKnownHosts parses an entry in the format of the known_hosts file. +// +// The known_hosts format is documented in the sshd(8) manual page. This +// function will parse a single entry from in. On successful return, marker +// will contain the optional marker value (i.e. "cert-authority" or "revoked") +// or else be empty, hosts will contain the hosts that this entry matches, +// pubKey will contain the public key and comment will contain any trailing +// comment at the end of the line. See the sshd(8) manual page for the various +// forms that a host string can take. +// +// The unparsed remainder of the input will be returned in rest. This function +// can be called repeatedly to parse multiple entries. +// +// If no entries were found in the input then err will be io.EOF. Otherwise a +// non-nil err value indicates a parse error. +func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) { + for len(in) > 0 { + end := bytes.IndexByte(in, '\n') + if end != -1 { + rest = in[end+1:] + in = in[:end] + } else { + rest = nil + } + + end = bytes.IndexByte(in, '\r') + if end != -1 { + in = in[:end] + } + + in = bytes.TrimSpace(in) + if len(in) == 0 || in[0] == '#' { + in = rest + continue + } + + i := bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + // Strip out the beginning of the known_host key. + // This is either an optional marker or a (set of) hostname(s). + keyFields := bytes.Fields(in) + if len(keyFields) < 3 || len(keyFields) > 5 { + return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data") + } + + // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated + // list of hosts + marker := "" + if keyFields[0][0] == '@' { + marker = string(keyFields[0][1:]) + keyFields = keyFields[1:] + } + + hosts := string(keyFields[0]) + // keyFields[1] contains the key type (e.g. “ssh-rsa”). + // However, that information is duplicated inside the + // base64-encoded key and so is ignored here. + + key := bytes.Join(keyFields[2:], []byte(" ")) + if pubKey, comment, err = parseAuthorizedKey(key); err != nil { + return "", nil, nil, "", nil, err + } + + return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil + } + + return "", nil, nil, "", nil, io.EOF +} + +// ParseAuthorizedKeys parses a public key from an authorized_keys +// file used in OpenSSH according to the sshd(8) manual page. +func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { + for len(in) > 0 { + end := bytes.IndexByte(in, '\n') + if end != -1 { + rest = in[end+1:] + in = in[:end] + } else { + rest = nil + } + + end = bytes.IndexByte(in, '\r') + if end != -1 { + in = in[:end] + } + + in = bytes.TrimSpace(in) + if len(in) == 0 || in[0] == '#' { + in = rest + continue + } + + i := bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { + return out, comment, options, rest, nil + } + + // No key type recognised. Maybe there's an options field at + // the beginning. + var b byte + inQuote := false + var candidateOptions []string + optionStart := 0 + for i, b = range in { + isEnd := !inQuote && (b == ' ' || b == '\t') + if (b == ',' && !inQuote) || isEnd { + if i-optionStart > 0 { + candidateOptions = append(candidateOptions, string(in[optionStart:i])) + } + optionStart = i + 1 + } + if isEnd { + break + } + if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { + inQuote = !inQuote + } + } + for i < len(in) && (in[i] == ' ' || in[i] == '\t') { + i++ + } + if i == len(in) { + // Invalid line: unmatched quote + in = rest + continue + } + + in = in[i:] + i = bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { + options = candidateOptions + return out, comment, options, rest, nil + } + + in = rest + continue + } + + return nil, "", nil, nil, errors.New("ssh: no key found") +} + +// ParsePublicKey parses an SSH public key formatted for use in +// the SSH wire protocol according to RFC 4253, section 6.6. +func ParsePublicKey(in []byte) (out PublicKey, err error) { + algo, in, ok := parseString(in) + if !ok { + return nil, errShortRead + } + var rest []byte + out, rest, err = parsePubKey(in, string(algo)) + if len(rest) > 0 { + return nil, errors.New("ssh: trailing junk in public key") + } + + return out, err +} + +// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH +// authorized_keys file. The return value ends with newline. +func MarshalAuthorizedKey(key PublicKey) []byte { + b := &bytes.Buffer{} + b.WriteString(key.Type()) + b.WriteByte(' ') + e := base64.NewEncoder(base64.StdEncoding, b) + e.Write(key.Marshal()) + e.Close() + b.WriteByte('\n') + return b.Bytes() +} + +// PublicKey represents a public key using an unspecified algorithm. +// +// Some PublicKeys provided by this package also implement CryptoPublicKey. +type PublicKey interface { + // Type returns the key format name, e.g. "ssh-rsa". + Type() string + + // Marshal returns the serialized key data in SSH wire format, with the name + // prefix. To unmarshal the returned data, use the ParsePublicKey function. + Marshal() []byte + + // Verify that sig is a signature on the given data using this key. This + // method will hash the data appropriately first. sig.Format is allowed to + // be any signature algorithm compatible with the key type, the caller + // should check if it has more stringent requirements. + Verify(data []byte, sig *Signature) error +} + +// CryptoPublicKey, if implemented by a PublicKey, +// returns the underlying crypto.PublicKey form of the key. +type CryptoPublicKey interface { + CryptoPublicKey() crypto.PublicKey +} + +// A Signer can create signatures that verify against a public key. +// +// Some Signers provided by this package also implement AlgorithmSigner. +type Signer interface { + // PublicKey returns the associated PublicKey. + PublicKey() PublicKey + + // Sign returns a signature for the given data. This method will hash the + // data appropriately first. The signature algorithm is expected to match + // the key format returned by the PublicKey.Type method (and not to be any + // alternative algorithm supported by the key format). + Sign(rand io.Reader, data []byte) (*Signature, error) +} + +// An AlgorithmSigner is a Signer that also supports specifying an algorithm to +// use for signing. +// +// An AlgorithmSigner can't advertise the algorithms it supports, so it should +// be prepared to be invoked with every algorithm supported by the public key +// format. +type AlgorithmSigner interface { + Signer + + // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired + // signing algorithm. Callers may pass an empty string for the algorithm in + // which case the AlgorithmSigner will use a default algorithm. This default + // doesn't currently control any behavior in this package. + SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) +} + +type rsaPublicKey rsa.PublicKey + +func (r *rsaPublicKey) Type() string { + return "ssh-rsa" +} + +// parseRSA parses an RSA key according to RFC 4253, section 6.6. +func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + E *big.Int + N *big.Int + Rest []byte `ssh:"rest"` + } + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + if w.E.BitLen() > 24 { + return nil, nil, errors.New("ssh: exponent too large") + } + e := w.E.Int64() + if e < 3 || e&1 == 0 { + return nil, nil, errors.New("ssh: incorrect exponent") + } + + var key rsa.PublicKey + key.E = int(e) + key.N = w.N + return (*rsaPublicKey)(&key), w.Rest, nil +} + +func (r *rsaPublicKey) Marshal() []byte { + e := new(big.Int).SetInt64(int64(r.E)) + // RSA publickey struct layout should match the struct used by + // parseRSACert in the x/crypto/ssh/agent package. + wirekey := struct { + Name string + E *big.Int + N *big.Int + }{ + KeyAlgoRSA, + e, + r.N, + } + return Marshal(&wirekey) +} + +func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { + supportedAlgos := algorithmsForKeyFormat(r.Type()) + if !contains(supportedAlgos, sig.Format) { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) + } + hash := hashFuncs[sig.Format] + h := hash.New() + h.Write(data) + digest := h.Sum(nil) + return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, sig.Blob) +} + +func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey { + return (*rsa.PublicKey)(r) +} + +type dsaPublicKey dsa.PublicKey + +func (k *dsaPublicKey) Type() string { + return "ssh-dss" +} + +func checkDSAParams(param *dsa.Parameters) error { + // SSH specifies FIPS 186-2, which only provided a single size + // (1024 bits) DSA key. FIPS 186-3 allows for larger key + // sizes, which would confuse SSH. + if l := param.P.BitLen(); l != 1024 { + return fmt.Errorf("ssh: unsupported DSA key size %d", l) + } + + return nil +} + +// parseDSA parses an DSA key according to RFC 4253, section 6.6. +func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + P, Q, G, Y *big.Int + Rest []byte `ssh:"rest"` + } + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + param := dsa.Parameters{ + P: w.P, + Q: w.Q, + G: w.G, + } + if err := checkDSAParams(¶m); err != nil { + return nil, nil, err + } + + key := &dsaPublicKey{ + Parameters: param, + Y: w.Y, + } + return key, w.Rest, nil +} + +func (k *dsaPublicKey) Marshal() []byte { + // DSA publickey struct layout should match the struct used by + // parseDSACert in the x/crypto/ssh/agent package. + w := struct { + Name string + P, Q, G, Y *big.Int + }{ + k.Type(), + k.P, + k.Q, + k.G, + k.Y, + } + + return Marshal(&w) +} + +func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + h := hashFuncs[sig.Format].New() + h.Write(data) + digest := h.Sum(nil) + + // Per RFC 4253, section 6.6, + // The value for 'dss_signature_blob' is encoded as a string containing + // r, followed by s (which are 160-bit integers, without lengths or + // padding, unsigned, and in network byte order). + // For DSS purposes, sig.Blob should be exactly 40 bytes in length. + if len(sig.Blob) != 40 { + return errors.New("ssh: DSA signature parse error") + } + r := new(big.Int).SetBytes(sig.Blob[:20]) + s := new(big.Int).SetBytes(sig.Blob[20:]) + if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey { + return (*dsa.PublicKey)(k) +} + +type dsaPrivateKey struct { + *dsa.PrivateKey +} + +func (k *dsaPrivateKey) PublicKey() PublicKey { + return (*dsaPublicKey)(&k.PrivateKey.PublicKey) +} + +func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { + return k.SignWithAlgorithm(rand, data, k.PublicKey().Type()) +} + +func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + if algorithm != "" && algorithm != k.PublicKey().Type() { + return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) + } + + h := hashFuncs[k.PublicKey().Type()].New() + h.Write(data) + digest := h.Sum(nil) + r, s, err := dsa.Sign(rand, k.PrivateKey, digest) + if err != nil { + return nil, err + } + + sig := make([]byte, 40) + rb := r.Bytes() + sb := s.Bytes() + + copy(sig[20-len(rb):20], rb) + copy(sig[40-len(sb):], sb) + + return &Signature{ + Format: k.PublicKey().Type(), + Blob: sig, + }, nil +} + +type ecdsaPublicKey ecdsa.PublicKey + +func (k *ecdsaPublicKey) Type() string { + return "ecdsa-sha2-" + k.nistID() +} + +func (k *ecdsaPublicKey) nistID() string { + switch k.Params().BitSize { + case 256: + return "nistp256" + case 384: + return "nistp384" + case 521: + return "nistp521" + } + panic("ssh: unsupported ecdsa key size") +} + +type ed25519PublicKey ed25519.PublicKey + +func (k ed25519PublicKey) Type() string { + return KeyAlgoED25519 +} + +func parseED25519(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + KeyBytes []byte + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + if l := len(w.KeyBytes); l != ed25519.PublicKeySize { + return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) + } + + return ed25519PublicKey(w.KeyBytes), w.Rest, nil +} + +func (k ed25519PublicKey) Marshal() []byte { + w := struct { + Name string + KeyBytes []byte + }{ + KeyAlgoED25519, + []byte(k), + } + return Marshal(&w) +} + +func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + if l := len(k); l != ed25519.PublicKeySize { + return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) + } + + if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok { + return errors.New("ssh: signature did not verify") + } + + return nil +} + +func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey { + return ed25519.PublicKey(k) +} + +func supportedEllipticCurve(curve elliptic.Curve) bool { + return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() +} + +// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. +func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + Curve string + KeyBytes []byte + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := new(ecdsa.PublicKey) + + switch w.Curve { + case "nistp256": + key.Curve = elliptic.P256() + case "nistp384": + key.Curve = elliptic.P384() + case "nistp521": + key.Curve = elliptic.P521() + default: + return nil, nil, errors.New("ssh: unsupported curve") + } + + key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) + if key.X == nil || key.Y == nil { + return nil, nil, errors.New("ssh: invalid curve point") + } + return (*ecdsaPublicKey)(key), w.Rest, nil +} + +func (k *ecdsaPublicKey) Marshal() []byte { + // See RFC 5656, section 3.1. + keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) + // ECDSA publickey struct layout should match the struct used by + // parseECDSACert in the x/crypto/ssh/agent package. + w := struct { + Name string + ID string + Key []byte + }{ + k.Type(), + k.nistID(), + keyBytes, + } + + return Marshal(&w) +} + +func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + + h := hashFuncs[sig.Format].New() + h.Write(data) + digest := h.Sum(nil) + + // Per RFC 5656, section 3.1.2, + // The ecdsa_signature_blob value has the following specific encoding: + // mpint r + // mpint s + var ecSig struct { + R *big.Int + S *big.Int + } + + if err := Unmarshal(sig.Blob, &ecSig); err != nil { + return err + } + + if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey { + return (*ecdsa.PublicKey)(k) +} + +// skFields holds the additional fields present in U2F/FIDO2 signatures. +// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details. +type skFields struct { + // Flags contains U2F/FIDO2 flags such as 'user present' + Flags byte + // Counter is a monotonic signature counter which can be + // used to detect concurrent use of a private key, should + // it be extracted from hardware. + Counter uint32 +} + +type skECDSAPublicKey struct { + // application is a URL-like string, typically "ssh:" for SSH. + // see openssh/PROTOCOL.u2f for details. + application string + ecdsa.PublicKey +} + +func (k *skECDSAPublicKey) Type() string { + return KeyAlgoSKECDSA256 +} + +func (k *skECDSAPublicKey) nistID() string { + return "nistp256" +} + +func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + Curve string + KeyBytes []byte + Application string + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := new(skECDSAPublicKey) + key.application = w.Application + + if w.Curve != "nistp256" { + return nil, nil, errors.New("ssh: unsupported curve") + } + key.Curve = elliptic.P256() + + key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) + if key.X == nil || key.Y == nil { + return nil, nil, errors.New("ssh: invalid curve point") + } + + return key, w.Rest, nil +} + +func (k *skECDSAPublicKey) Marshal() []byte { + // See RFC 5656, section 3.1. + keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) + w := struct { + Name string + ID string + Key []byte + Application string + }{ + k.Type(), + k.nistID(), + keyBytes, + k.application, + } + + return Marshal(&w) +} + +func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + + h := hashFuncs[sig.Format].New() + h.Write([]byte(k.application)) + appDigest := h.Sum(nil) + + h.Reset() + h.Write(data) + dataDigest := h.Sum(nil) + + var ecSig struct { + R *big.Int + S *big.Int + } + if err := Unmarshal(sig.Blob, &ecSig); err != nil { + return err + } + + var skf skFields + if err := Unmarshal(sig.Rest, &skf); err != nil { + return err + } + + blob := struct { + ApplicationDigest []byte `ssh:"rest"` + Flags byte + Counter uint32 + MessageDigest []byte `ssh:"rest"` + }{ + appDigest, + skf.Flags, + skf.Counter, + dataDigest, + } + + original := Marshal(blob) + + h.Reset() + h.Write(original) + digest := h.Sum(nil) + + if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +type skEd25519PublicKey struct { + // application is a URL-like string, typically "ssh:" for SSH. + // see openssh/PROTOCOL.u2f for details. + application string + ed25519.PublicKey +} + +func (k *skEd25519PublicKey) Type() string { + return KeyAlgoSKED25519 +} + +func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + KeyBytes []byte + Application string + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + if l := len(w.KeyBytes); l != ed25519.PublicKeySize { + return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) + } + + key := new(skEd25519PublicKey) + key.application = w.Application + key.PublicKey = ed25519.PublicKey(w.KeyBytes) + + return key, w.Rest, nil +} + +func (k *skEd25519PublicKey) Marshal() []byte { + w := struct { + Name string + KeyBytes []byte + Application string + }{ + KeyAlgoSKED25519, + []byte(k.PublicKey), + k.application, + } + return Marshal(&w) +} + +func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + if l := len(k.PublicKey); l != ed25519.PublicKeySize { + return fmt.Errorf("invalid size %d for Ed25519 public key", l) + } + + h := hashFuncs[sig.Format].New() + h.Write([]byte(k.application)) + appDigest := h.Sum(nil) + + h.Reset() + h.Write(data) + dataDigest := h.Sum(nil) + + var edSig struct { + Signature []byte `ssh:"rest"` + } + + if err := Unmarshal(sig.Blob, &edSig); err != nil { + return err + } + + var skf skFields + if err := Unmarshal(sig.Rest, &skf); err != nil { + return err + } + + blob := struct { + ApplicationDigest []byte `ssh:"rest"` + Flags byte + Counter uint32 + MessageDigest []byte `ssh:"rest"` + }{ + appDigest, + skf.Flags, + skf.Counter, + dataDigest, + } + + original := Marshal(blob) + + if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok { + return errors.New("ssh: signature did not verify") + } + + return nil +} + +// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, +// *ecdsa.PrivateKey or any other crypto.Signer and returns a +// corresponding Signer instance. ECDSA keys must use P-256, P-384 or +// P-521. DSA keys must use parameter size L1024N160. +func NewSignerFromKey(key interface{}) (Signer, error) { + switch key := key.(type) { + case crypto.Signer: + return NewSignerFromSigner(key) + case *dsa.PrivateKey: + return newDSAPrivateKey(key) + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } +} + +func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) { + if err := checkDSAParams(&key.PublicKey.Parameters); err != nil { + return nil, err + } + + return &dsaPrivateKey{key}, nil +} + +type wrappedSigner struct { + signer crypto.Signer + pubKey PublicKey +} + +// NewSignerFromSigner takes any crypto.Signer implementation and +// returns a corresponding Signer interface. This can be used, for +// example, with keys kept in hardware modules. +func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { + pubKey, err := NewPublicKey(signer.Public()) + if err != nil { + return nil, err + } + + return &wrappedSigner{signer, pubKey}, nil +} + +func (s *wrappedSigner) PublicKey() PublicKey { + return s.pubKey +} + +func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + return s.SignWithAlgorithm(rand, data, s.pubKey.Type()) +} + +func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + if algorithm == "" { + algorithm = s.pubKey.Type() + } + + supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type()) + if !contains(supportedAlgos, algorithm) { + return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type()) + } + + hashFunc := hashFuncs[algorithm] + var digest []byte + if hashFunc != 0 { + h := hashFunc.New() + h.Write(data) + digest = h.Sum(nil) + } else { + digest = data + } + + signature, err := s.signer.Sign(rand, digest, hashFunc) + if err != nil { + return nil, err + } + + // crypto.Signer.Sign is expected to return an ASN.1-encoded signature + // for ECDSA and DSA, but that's not the encoding expected by SSH, so + // re-encode. + switch s.pubKey.(type) { + case *ecdsaPublicKey, *dsaPublicKey: + type asn1Signature struct { + R, S *big.Int + } + asn1Sig := new(asn1Signature) + _, err := asn1.Unmarshal(signature, asn1Sig) + if err != nil { + return nil, err + } + + switch s.pubKey.(type) { + case *ecdsaPublicKey: + signature = Marshal(asn1Sig) + + case *dsaPublicKey: + signature = make([]byte, 40) + r := asn1Sig.R.Bytes() + s := asn1Sig.S.Bytes() + copy(signature[20-len(r):20], r) + copy(signature[40-len(s):40], s) + } + } + + return &Signature{ + Format: algorithm, + Blob: signature, + }, nil +} + +// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, +// or ed25519.PublicKey returns a corresponding PublicKey instance. +// ECDSA keys must use P-256, P-384 or P-521. +func NewPublicKey(key interface{}) (PublicKey, error) { + switch key := key.(type) { + case *rsa.PublicKey: + return (*rsaPublicKey)(key), nil + case *ecdsa.PublicKey: + if !supportedEllipticCurve(key.Curve) { + return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported") + } + return (*ecdsaPublicKey)(key), nil + case *dsa.PublicKey: + return (*dsaPublicKey)(key), nil + case ed25519.PublicKey: + if l := len(key); l != ed25519.PublicKeySize { + return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) + } + return ed25519PublicKey(key), nil + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } +} + +// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports +// the same keys as ParseRawPrivateKey. If the private key is encrypted, it +// will return a PassphraseMissingError. +func ParsePrivateKey(pemBytes []byte) (Signer, error) { + key, err := ParseRawPrivateKey(pemBytes) + if err != nil { + return nil, err + } + + return NewSignerFromKey(key) +} + +// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private +// key and passphrase. It supports the same keys as +// ParseRawPrivateKeyWithPassphrase. +func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) { + key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase) + if err != nil { + return nil, err + } + + return NewSignerFromKey(key) +} + +// encryptedBlock tells whether a private key is +// encrypted by examining its Proc-Type header +// for a mention of ENCRYPTED +// according to RFC 1421 Section 4.6.1.1. +func encryptedBlock(block *pem.Block) bool { + return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") +} + +// A PassphraseMissingError indicates that parsing this private key requires a +// passphrase. Use ParsePrivateKeyWithPassphrase. +type PassphraseMissingError struct { + // PublicKey will be set if the private key format includes an unencrypted + // public key along with the encrypted private key. + PublicKey PublicKey +} + +func (*PassphraseMissingError) Error() string { + return "ssh: this private key is passphrase protected" +} + +// ParseRawPrivateKey returns a private key from a PEM encoded private key. It +// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the +// private key is encrypted, it will return a PassphraseMissingError. +func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { + block, _ := pem.Decode(pemBytes) + if block == nil { + return nil, errors.New("ssh: no key found") + } + + if encryptedBlock(block) { + return nil, &PassphraseMissingError{} + } + + switch block.Type { + case "RSA PRIVATE KEY": + return x509.ParsePKCS1PrivateKey(block.Bytes) + // RFC5208 - https://tools.ietf.org/html/rfc5208 + case "PRIVATE KEY": + return x509.ParsePKCS8PrivateKey(block.Bytes) + case "EC PRIVATE KEY": + return x509.ParseECPrivateKey(block.Bytes) + case "DSA PRIVATE KEY": + return ParseDSAPrivateKey(block.Bytes) + case "OPENSSH PRIVATE KEY": + return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey) + default: + return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) + } +} + +// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with +// passphrase from a PEM encoded private key. If the passphrase is wrong, it +// will return x509.IncorrectPasswordError. +func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) { + block, _ := pem.Decode(pemBytes) + if block == nil { + return nil, errors.New("ssh: no key found") + } + + if block.Type == "OPENSSH PRIVATE KEY" { + return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase)) + } + + if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) { + return nil, errors.New("ssh: not an encrypted key") + } + + buf, err := x509.DecryptPEMBlock(block, passphrase) + if err != nil { + if err == x509.IncorrectPasswordError { + return nil, err + } + return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err) + } + + switch block.Type { + case "RSA PRIVATE KEY": + return x509.ParsePKCS1PrivateKey(buf) + case "EC PRIVATE KEY": + return x509.ParseECPrivateKey(buf) + case "DSA PRIVATE KEY": + return ParseDSAPrivateKey(buf) + default: + return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) + } +} + +// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as +// specified by the OpenSSL DSA man page. +func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { + var k struct { + Version int + P *big.Int + Q *big.Int + G *big.Int + Pub *big.Int + Priv *big.Int + } + rest, err := asn1.Unmarshal(der, &k) + if err != nil { + return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) + } + if len(rest) > 0 { + return nil, errors.New("ssh: garbage after DSA key") + } + + return &dsa.PrivateKey{ + PublicKey: dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: k.P, + Q: k.Q, + G: k.G, + }, + Y: k.Pub, + }, + X: k.Priv, + }, nil +} + +func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { + if kdfName != "none" || cipherName != "none" { + return nil, &PassphraseMissingError{} + } + if kdfOpts != "" { + return nil, errors.New("ssh: invalid openssh private key") + } + return privKeyBlock, nil +} + +func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc { + return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { + if kdfName == "none" || cipherName == "none" { + return nil, errors.New("ssh: key is not password protected") + } + if kdfName != "bcrypt" { + return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt") + } + + var opts struct { + Salt string + Rounds uint32 + } + if err := Unmarshal([]byte(kdfOpts), &opts); err != nil { + return nil, err + } + + k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16) + if err != nil { + return nil, err + } + key, iv := k[:32], k[32:] + + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + switch cipherName { + case "aes256-ctr": + ctr := cipher.NewCTR(c, iv) + ctr.XORKeyStream(privKeyBlock, privKeyBlock) + case "aes256-cbc": + if len(privKeyBlock)%c.BlockSize() != 0 { + return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size") + } + cbc := cipher.NewCBCDecrypter(c, iv) + cbc.CryptBlocks(privKeyBlock, privKeyBlock) + default: + return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc") + } + + return privKeyBlock, nil + } +} + +type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error) + +// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt +// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used +// as the decrypt function to parse an unencrypted private key. See +// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key. +func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) { + const magic = "openssh-key-v1\x00" + if len(key) < len(magic) || string(key[:len(magic)]) != magic { + return nil, errors.New("ssh: invalid openssh private key format") + } + remaining := key[len(magic):] + + var w struct { + CipherName string + KdfName string + KdfOpts string + NumKeys uint32 + PubKey []byte + PrivKeyBlock []byte + } + + if err := Unmarshal(remaining, &w); err != nil { + return nil, err + } + if w.NumKeys != 1 { + // We only support single key files, and so does OpenSSH. + // https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171 + return nil, errors.New("ssh: multi-key files are not supported") + } + + privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock) + if err != nil { + if err, ok := err.(*PassphraseMissingError); ok { + pub, errPub := ParsePublicKey(w.PubKey) + if errPub != nil { + return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub) + } + err.PublicKey = pub + } + return nil, err + } + + pk1 := struct { + Check1 uint32 + Check2 uint32 + Keytype string + Rest []byte `ssh:"rest"` + }{} + + if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 { + if w.CipherName != "none" { + return nil, x509.IncorrectPasswordError + } + return nil, errors.New("ssh: malformed OpenSSH key") + } + + switch pk1.Keytype { + case KeyAlgoRSA: + // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 + key := struct { + N *big.Int + E *big.Int + D *big.Int + Iqmp *big.Int + P *big.Int + Q *big.Int + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + if err := checkOpenSSHKeyPadding(key.Pad); err != nil { + return nil, err + } + + pk := &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: key.N, + E: int(key.E.Int64()), + }, + D: key.D, + Primes: []*big.Int{key.P, key.Q}, + } + + if err := pk.Validate(); err != nil { + return nil, err + } + + pk.Precompute() + + return pk, nil + case KeyAlgoED25519: + key := struct { + Pub []byte + Priv []byte + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + if len(key.Priv) != ed25519.PrivateKeySize { + return nil, errors.New("ssh: private key unexpected length") + } + + if err := checkOpenSSHKeyPadding(key.Pad); err != nil { + return nil, err + } + + pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) + copy(pk, key.Priv) + return &pk, nil + case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: + key := struct { + Curve string + Pub []byte + D *big.Int + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + if err := checkOpenSSHKeyPadding(key.Pad); err != nil { + return nil, err + } + + var curve elliptic.Curve + switch key.Curve { + case "nistp256": + curve = elliptic.P256() + case "nistp384": + curve = elliptic.P384() + case "nistp521": + curve = elliptic.P521() + default: + return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve) + } + + X, Y := elliptic.Unmarshal(curve, key.Pub) + if X == nil || Y == nil { + return nil, errors.New("ssh: failed to unmarshal public key") + } + + if key.D.Cmp(curve.Params().N) >= 0 { + return nil, errors.New("ssh: scalar is out of range") + } + + x, y := curve.ScalarBaseMult(key.D.Bytes()) + if x.Cmp(X) != 0 || y.Cmp(Y) != 0 { + return nil, errors.New("ssh: public key does not match private key") + } + + return &ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: curve, + X: X, + Y: Y, + }, + D: key.D, + }, nil + default: + return nil, errors.New("ssh: unhandled key type") + } +} + +func checkOpenSSHKeyPadding(pad []byte) error { + for i, b := range pad { + if int(b) != i+1 { + return errors.New("ssh: padding not as expected") + } + } + return nil +} + +// FingerprintLegacyMD5 returns the user presentation of the key's +// fingerprint as described by RFC 4716 section 4. +func FingerprintLegacyMD5(pubKey PublicKey) string { + md5sum := md5.Sum(pubKey.Marshal()) + hexarray := make([]string, len(md5sum)) + for i, c := range md5sum { + hexarray[i] = hex.EncodeToString([]byte{c}) + } + return strings.Join(hexarray, ":") +} + +// FingerprintSHA256 returns the user presentation of the key's +// fingerprint as unpadded base64 encoded sha256 hash. +// This format was introduced from OpenSSH 6.8. +// https://www.openssh.com/txt/release-6.8 +// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding) +func FingerprintSHA256(pubKey PublicKey) string { + sha256sum := sha256.Sum256(pubKey.Marshal()) + hash := base64.RawStdEncoding.EncodeToString(sha256sum[:]) + return "SHA256:" + hash +} diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go new file mode 100644 index 00000000..c07a0628 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mac.go @@ -0,0 +1,61 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +// Message authentication support + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "hash" +) + +type macMode struct { + keySize int + etm bool + new func(key []byte) hash.Hash +} + +// truncatingMAC wraps around a hash.Hash and truncates the output digest to +// a given size. +type truncatingMAC struct { + length int + hmac hash.Hash +} + +func (t truncatingMAC) Write(data []byte) (int, error) { + return t.hmac.Write(data) +} + +func (t truncatingMAC) Sum(in []byte) []byte { + out := t.hmac.Sum(in) + return out[:len(in)+t.length] +} + +func (t truncatingMAC) Reset() { + t.hmac.Reset() +} + +func (t truncatingMAC) Size() int { + return t.length +} + +func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } + +var macModes = map[string]*macMode{ + "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { + return hmac.New(sha256.New, key) + }}, + "hmac-sha2-256": {32, false, func(key []byte) hash.Hash { + return hmac.New(sha256.New, key) + }}, + "hmac-sha1": {20, false, func(key []byte) hash.Hash { + return hmac.New(sha1.New, key) + }}, + "hmac-sha1-96": {20, false, func(key []byte) hash.Hash { + return truncatingMAC{12, hmac.New(sha1.New, key)} + }}, +} diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go new file mode 100644 index 00000000..19bc67c4 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -0,0 +1,877 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "reflect" + "strconv" + "strings" +) + +// These are SSH message type numbers. They are scattered around several +// documents but many were taken from [SSH-PARAMETERS]. +const ( + msgIgnore = 2 + msgUnimplemented = 3 + msgDebug = 4 + msgNewKeys = 21 +) + +// SSH messages: +// +// These structures mirror the wire format of the corresponding SSH messages. +// They are marshaled using reflection with the marshal and unmarshal functions +// in this file. The only wrinkle is that a final member of type []byte with a +// ssh tag of "rest" receives the remainder of a packet when unmarshaling. + +// See RFC 4253, section 11.1. +const msgDisconnect = 1 + +// disconnectMsg is the message that signals a disconnect. It is also +// the error type returned from mux.Wait() +type disconnectMsg struct { + Reason uint32 `sshtype:"1"` + Message string + Language string +} + +func (d *disconnectMsg) Error() string { + return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message) +} + +// See RFC 4253, section 7.1. +const msgKexInit = 20 + +type kexInitMsg struct { + Cookie [16]byte `sshtype:"20"` + KexAlgos []string + ServerHostKeyAlgos []string + CiphersClientServer []string + CiphersServerClient []string + MACsClientServer []string + MACsServerClient []string + CompressionClientServer []string + CompressionServerClient []string + LanguagesClientServer []string + LanguagesServerClient []string + FirstKexFollows bool + Reserved uint32 +} + +// See RFC 4253, section 8. + +// Diffie-Helman +const msgKexDHInit = 30 + +type kexDHInitMsg struct { + X *big.Int `sshtype:"30"` +} + +const msgKexECDHInit = 30 + +type kexECDHInitMsg struct { + ClientPubKey []byte `sshtype:"30"` +} + +const msgKexECDHReply = 31 + +type kexECDHReplyMsg struct { + HostKey []byte `sshtype:"31"` + EphemeralPubKey []byte + Signature []byte +} + +const msgKexDHReply = 31 + +type kexDHReplyMsg struct { + HostKey []byte `sshtype:"31"` + Y *big.Int + Signature []byte +} + +// See RFC 4419, section 5. +const msgKexDHGexGroup = 31 + +type kexDHGexGroupMsg struct { + P *big.Int `sshtype:"31"` + G *big.Int +} + +const msgKexDHGexInit = 32 + +type kexDHGexInitMsg struct { + X *big.Int `sshtype:"32"` +} + +const msgKexDHGexReply = 33 + +type kexDHGexReplyMsg struct { + HostKey []byte `sshtype:"33"` + Y *big.Int + Signature []byte +} + +const msgKexDHGexRequest = 34 + +type kexDHGexRequestMsg struct { + MinBits uint32 `sshtype:"34"` + PreferedBits uint32 + MaxBits uint32 +} + +// See RFC 4253, section 10. +const msgServiceRequest = 5 + +type serviceRequestMsg struct { + Service string `sshtype:"5"` +} + +// See RFC 4253, section 10. +const msgServiceAccept = 6 + +type serviceAcceptMsg struct { + Service string `sshtype:"6"` +} + +// See RFC 8308, section 2.3 +const msgExtInfo = 7 + +type extInfoMsg struct { + NumExtensions uint32 `sshtype:"7"` + Payload []byte `ssh:"rest"` +} + +// See RFC 4252, section 5. +const msgUserAuthRequest = 50 + +type userAuthRequestMsg struct { + User string `sshtype:"50"` + Service string + Method string + Payload []byte `ssh:"rest"` +} + +// Used for debug printouts of packets. +type userAuthSuccessMsg struct { +} + +// See RFC 4252, section 5.1 +const msgUserAuthFailure = 51 + +type userAuthFailureMsg struct { + Methods []string `sshtype:"51"` + PartialSuccess bool +} + +// See RFC 4252, section 5.1 +const msgUserAuthSuccess = 52 + +// See RFC 4252, section 5.4 +const msgUserAuthBanner = 53 + +type userAuthBannerMsg struct { + Message string `sshtype:"53"` + // unused, but required to allow message parsing + Language string +} + +// See RFC 4256, section 3.2 +const msgUserAuthInfoRequest = 60 +const msgUserAuthInfoResponse = 61 + +type userAuthInfoRequestMsg struct { + Name string `sshtype:"60"` + Instruction string + Language string + NumPrompts uint32 + Prompts []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpen = 90 + +type channelOpenMsg struct { + ChanType string `sshtype:"90"` + PeersID uint32 + PeersWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte `ssh:"rest"` +} + +const msgChannelExtendedData = 95 +const msgChannelData = 94 + +// Used for debug print outs of packets. +type channelDataMsg struct { + PeersID uint32 `sshtype:"94"` + Length uint32 + Rest []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpenConfirm = 91 + +type channelOpenConfirmMsg struct { + PeersID uint32 `sshtype:"91"` + MyID uint32 + MyWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpenFailure = 92 + +type channelOpenFailureMsg struct { + PeersID uint32 `sshtype:"92"` + Reason RejectionReason + Message string + Language string +} + +const msgChannelRequest = 98 + +type channelRequestMsg struct { + PeersID uint32 `sshtype:"98"` + Request string + WantReply bool + RequestSpecificData []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.4. +const msgChannelSuccess = 99 + +type channelRequestSuccessMsg struct { + PeersID uint32 `sshtype:"99"` +} + +// See RFC 4254, section 5.4. +const msgChannelFailure = 100 + +type channelRequestFailureMsg struct { + PeersID uint32 `sshtype:"100"` +} + +// See RFC 4254, section 5.3 +const msgChannelClose = 97 + +type channelCloseMsg struct { + PeersID uint32 `sshtype:"97"` +} + +// See RFC 4254, section 5.3 +const msgChannelEOF = 96 + +type channelEOFMsg struct { + PeersID uint32 `sshtype:"96"` +} + +// See RFC 4254, section 4 +const msgGlobalRequest = 80 + +type globalRequestMsg struct { + Type string `sshtype:"80"` + WantReply bool + Data []byte `ssh:"rest"` +} + +// See RFC 4254, section 4 +const msgRequestSuccess = 81 + +type globalRequestSuccessMsg struct { + Data []byte `ssh:"rest" sshtype:"81"` +} + +// See RFC 4254, section 4 +const msgRequestFailure = 82 + +type globalRequestFailureMsg struct { + Data []byte `ssh:"rest" sshtype:"82"` +} + +// See RFC 4254, section 5.2 +const msgChannelWindowAdjust = 93 + +type windowAdjustMsg struct { + PeersID uint32 `sshtype:"93"` + AdditionalBytes uint32 +} + +// See RFC 4252, section 7 +const msgUserAuthPubKeyOk = 60 + +type userAuthPubKeyOkMsg struct { + Algo string `sshtype:"60"` + PubKey []byte +} + +// See RFC 4462, section 3 +const msgUserAuthGSSAPIResponse = 60 + +type userAuthGSSAPIResponse struct { + SupportMech []byte `sshtype:"60"` +} + +const msgUserAuthGSSAPIToken = 61 + +type userAuthGSSAPIToken struct { + Token []byte `sshtype:"61"` +} + +const msgUserAuthGSSAPIMIC = 66 + +type userAuthGSSAPIMIC struct { + MIC []byte `sshtype:"66"` +} + +// See RFC 4462, section 3.9 +const msgUserAuthGSSAPIErrTok = 64 + +type userAuthGSSAPIErrTok struct { + ErrorToken []byte `sshtype:"64"` +} + +// See RFC 4462, section 3.8 +const msgUserAuthGSSAPIError = 65 + +type userAuthGSSAPIError struct { + MajorStatus uint32 `sshtype:"65"` + MinorStatus uint32 + Message string + LanguageTag string +} + +// typeTags returns the possible type bytes for the given reflect.Type, which +// should be a struct. The possible values are separated by a '|' character. +func typeTags(structType reflect.Type) (tags []byte) { + tagStr := structType.Field(0).Tag.Get("sshtype") + + for _, tag := range strings.Split(tagStr, "|") { + i, err := strconv.Atoi(tag) + if err == nil { + tags = append(tags, byte(i)) + } + } + + return tags +} + +func fieldError(t reflect.Type, field int, problem string) error { + if problem != "" { + problem = ": " + problem + } + return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem) +} + +var errShortRead = errors.New("ssh: short read") + +// Unmarshal parses data in SSH wire format into a structure. The out +// argument should be a pointer to struct. If the first member of the +// struct has the "sshtype" tag set to a '|'-separated set of numbers +// in decimal, the packet must start with one of those numbers. In +// case of error, Unmarshal returns a ParseError or +// UnexpectedMessageError. +func Unmarshal(data []byte, out interface{}) error { + v := reflect.ValueOf(out).Elem() + structType := v.Type() + expectedTypes := typeTags(structType) + + var expectedType byte + if len(expectedTypes) > 0 { + expectedType = expectedTypes[0] + } + + if len(data) == 0 { + return parseError(expectedType) + } + + if len(expectedTypes) > 0 { + goodType := false + for _, e := range expectedTypes { + if e > 0 && data[0] == e { + goodType = true + break + } + } + if !goodType { + return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes) + } + data = data[1:] + } + + var ok bool + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + t := field.Type() + switch t.Kind() { + case reflect.Bool: + if len(data) < 1 { + return errShortRead + } + field.SetBool(data[0] != 0) + data = data[1:] + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + return fieldError(structType, i, "array of unsupported type") + } + if len(data) < t.Len() { + return errShortRead + } + for j, n := 0, t.Len(); j < n; j++ { + field.Index(j).Set(reflect.ValueOf(data[j])) + } + data = data[t.Len():] + case reflect.Uint64: + var u64 uint64 + if u64, data, ok = parseUint64(data); !ok { + return errShortRead + } + field.SetUint(u64) + case reflect.Uint32: + var u32 uint32 + if u32, data, ok = parseUint32(data); !ok { + return errShortRead + } + field.SetUint(uint64(u32)) + case reflect.Uint8: + if len(data) < 1 { + return errShortRead + } + field.SetUint(uint64(data[0])) + data = data[1:] + case reflect.String: + var s []byte + if s, data, ok = parseString(data); !ok { + return fieldError(structType, i, "") + } + field.SetString(string(s)) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if structType.Field(i).Tag.Get("ssh") == "rest" { + field.Set(reflect.ValueOf(data)) + data = nil + } else { + var s []byte + if s, data, ok = parseString(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(s)) + } + case reflect.String: + var nl []string + if nl, data, ok = parseNameList(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(nl)) + default: + return fieldError(structType, i, "slice of unsupported type") + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + if n, data, ok = parseInt(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(n)) + } else { + return fieldError(structType, i, "pointer to unsupported type") + } + default: + return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t)) + } + } + + if len(data) != 0 { + return parseError(expectedType) + } + + return nil +} + +// Marshal serializes the message in msg to SSH wire format. The msg +// argument should be a struct or pointer to struct. If the first +// member has the "sshtype" tag set to a number in decimal, that +// number is prepended to the result. If the last of member has the +// "ssh" tag set to "rest", its contents are appended to the output. +func Marshal(msg interface{}) []byte { + out := make([]byte, 0, 64) + return marshalStruct(out, msg) +} + +func marshalStruct(out []byte, msg interface{}) []byte { + v := reflect.Indirect(reflect.ValueOf(msg)) + msgTypes := typeTags(v.Type()) + if len(msgTypes) > 0 { + out = append(out, msgTypes[0]) + } + + for i, n := 0, v.NumField(); i < n; i++ { + field := v.Field(i) + switch t := field.Type(); t.Kind() { + case reflect.Bool: + var v uint8 + if field.Bool() { + v = 1 + } + out = append(out, v) + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface())) + } + for j, l := 0, t.Len(); j < l; j++ { + out = append(out, uint8(field.Index(j).Uint())) + } + case reflect.Uint32: + out = appendU32(out, uint32(field.Uint())) + case reflect.Uint64: + out = appendU64(out, uint64(field.Uint())) + case reflect.Uint8: + out = append(out, uint8(field.Uint())) + case reflect.String: + s := field.String() + out = appendInt(out, len(s)) + out = append(out, s...) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if v.Type().Field(i).Tag.Get("ssh") != "rest" { + out = appendInt(out, field.Len()) + } + out = append(out, field.Bytes()...) + case reflect.String: + offset := len(out) + out = appendU32(out, 0) + if n := field.Len(); n > 0 { + for j := 0; j < n; j++ { + f := field.Index(j) + if j != 0 { + out = append(out, ',') + } + out = append(out, f.String()...) + } + // overwrite length value + binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4)) + } + default: + panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface())) + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + nValue := reflect.ValueOf(&n) + nValue.Elem().Set(field) + needed := intLength(n) + oldLength := len(out) + + if cap(out)-len(out) < needed { + newOut := make([]byte, len(out), 2*(len(out)+needed)) + copy(newOut, out) + out = newOut + } + out = out[:oldLength+needed] + marshalInt(out[oldLength:], n) + } else { + panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface())) + } + } + } + + return out +} + +var bigOne = big.NewInt(1) + +func parseString(in []byte) (out, rest []byte, ok bool) { + if len(in) < 4 { + return + } + length := binary.BigEndian.Uint32(in) + in = in[4:] + if uint32(len(in)) < length { + return + } + out = in[:length] + rest = in[length:] + ok = true + return +} + +var ( + comma = []byte{','} + emptyNameList = []string{} +) + +func parseNameList(in []byte) (out []string, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + if len(contents) == 0 { + out = emptyNameList + return + } + parts := bytes.Split(contents, comma) + out = make([]string, len(parts)) + for i, part := range parts { + out[i] = string(part) + } + return +} + +func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + out = new(big.Int) + + if len(contents) > 0 && contents[0]&0x80 == 0x80 { + // This is a negative number + notBytes := make([]byte, len(contents)) + for i := range notBytes { + notBytes[i] = ^contents[i] + } + out.SetBytes(notBytes) + out.Add(out, bigOne) + out.Neg(out) + } else { + // Positive number + out.SetBytes(contents) + } + ok = true + return +} + +func parseUint32(in []byte) (uint32, []byte, bool) { + if len(in) < 4 { + return 0, nil, false + } + return binary.BigEndian.Uint32(in), in[4:], true +} + +func parseUint64(in []byte) (uint64, []byte, bool) { + if len(in) < 8 { + return 0, nil, false + } + return binary.BigEndian.Uint64(in), in[8:], true +} + +func intLength(n *big.Int) int { + length := 4 /* length bytes */ + if n.Sign() < 0 { + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bitLen := nMinus1.BitLen() + if bitLen%8 == 0 { + // The number will need 0xff padding + length++ + } + length += (bitLen + 7) / 8 + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bitLen := n.BitLen() + if bitLen%8 == 0 { + // The number will need 0x00 padding + length++ + } + length += (bitLen + 7) / 8 + } + + return length +} + +func marshalUint32(to []byte, n uint32) []byte { + binary.BigEndian.PutUint32(to, n) + return to[4:] +} + +func marshalUint64(to []byte, n uint64) []byte { + binary.BigEndian.PutUint64(to, n) + return to[8:] +} + +func marshalInt(to []byte, n *big.Int) []byte { + lengthBytes := to + to = to[4:] + length := 0 + + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement + // form. So we'll subtract 1 and invert. If the + // most-significant-bit isn't set then we'll need to pad the + // beginning with 0xff in order to keep the number negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + to[0] = 0xff + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { + // We'll have to pad this with a 0x00 in order to + // stop it looking like a negative number. + to[0] = 0 + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } + + lengthBytes[0] = byte(length >> 24) + lengthBytes[1] = byte(length >> 16) + lengthBytes[2] = byte(length >> 8) + lengthBytes[3] = byte(length) + return to +} + +func writeInt(w io.Writer, n *big.Int) { + length := intLength(n) + buf := make([]byte, length) + marshalInt(buf, n) + w.Write(buf) +} + +func writeString(w io.Writer, s []byte) { + var lengthBytes [4]byte + lengthBytes[0] = byte(len(s) >> 24) + lengthBytes[1] = byte(len(s) >> 16) + lengthBytes[2] = byte(len(s) >> 8) + lengthBytes[3] = byte(len(s)) + w.Write(lengthBytes[:]) + w.Write(s) +} + +func stringLength(n int) int { + return 4 + n +} + +func marshalString(to []byte, s []byte) []byte { + to[0] = byte(len(s) >> 24) + to[1] = byte(len(s) >> 16) + to[2] = byte(len(s) >> 8) + to[3] = byte(len(s)) + to = to[4:] + copy(to, s) + return to[len(s):] +} + +var bigIntType = reflect.TypeOf((*big.Int)(nil)) + +// Decode a packet into its corresponding message. +func decode(packet []byte) (interface{}, error) { + var msg interface{} + switch packet[0] { + case msgDisconnect: + msg = new(disconnectMsg) + case msgServiceRequest: + msg = new(serviceRequestMsg) + case msgServiceAccept: + msg = new(serviceAcceptMsg) + case msgExtInfo: + msg = new(extInfoMsg) + case msgKexInit: + msg = new(kexInitMsg) + case msgKexDHInit: + msg = new(kexDHInitMsg) + case msgKexDHReply: + msg = new(kexDHReplyMsg) + case msgUserAuthRequest: + msg = new(userAuthRequestMsg) + case msgUserAuthSuccess: + return new(userAuthSuccessMsg), nil + case msgUserAuthFailure: + msg = new(userAuthFailureMsg) + case msgUserAuthPubKeyOk: + msg = new(userAuthPubKeyOkMsg) + case msgGlobalRequest: + msg = new(globalRequestMsg) + case msgRequestSuccess: + msg = new(globalRequestSuccessMsg) + case msgRequestFailure: + msg = new(globalRequestFailureMsg) + case msgChannelOpen: + msg = new(channelOpenMsg) + case msgChannelData: + msg = new(channelDataMsg) + case msgChannelOpenConfirm: + msg = new(channelOpenConfirmMsg) + case msgChannelOpenFailure: + msg = new(channelOpenFailureMsg) + case msgChannelWindowAdjust: + msg = new(windowAdjustMsg) + case msgChannelEOF: + msg = new(channelEOFMsg) + case msgChannelClose: + msg = new(channelCloseMsg) + case msgChannelRequest: + msg = new(channelRequestMsg) + case msgChannelSuccess: + msg = new(channelRequestSuccessMsg) + case msgChannelFailure: + msg = new(channelRequestFailureMsg) + case msgUserAuthGSSAPIToken: + msg = new(userAuthGSSAPIToken) + case msgUserAuthGSSAPIMIC: + msg = new(userAuthGSSAPIMIC) + case msgUserAuthGSSAPIErrTok: + msg = new(userAuthGSSAPIErrTok) + case msgUserAuthGSSAPIError: + msg = new(userAuthGSSAPIError) + default: + return nil, unexpectedMessageError(0, packet[0]) + } + if err := Unmarshal(packet, msg); err != nil { + return nil, err + } + return msg, nil +} + +var packetTypeNames = map[byte]string{ + msgDisconnect: "disconnectMsg", + msgServiceRequest: "serviceRequestMsg", + msgServiceAccept: "serviceAcceptMsg", + msgExtInfo: "extInfoMsg", + msgKexInit: "kexInitMsg", + msgKexDHInit: "kexDHInitMsg", + msgKexDHReply: "kexDHReplyMsg", + msgUserAuthRequest: "userAuthRequestMsg", + msgUserAuthSuccess: "userAuthSuccessMsg", + msgUserAuthFailure: "userAuthFailureMsg", + msgUserAuthPubKeyOk: "userAuthPubKeyOkMsg", + msgGlobalRequest: "globalRequestMsg", + msgRequestSuccess: "globalRequestSuccessMsg", + msgRequestFailure: "globalRequestFailureMsg", + msgChannelOpen: "channelOpenMsg", + msgChannelData: "channelDataMsg", + msgChannelOpenConfirm: "channelOpenConfirmMsg", + msgChannelOpenFailure: "channelOpenFailureMsg", + msgChannelWindowAdjust: "windowAdjustMsg", + msgChannelEOF: "channelEOFMsg", + msgChannelClose: "channelCloseMsg", + msgChannelRequest: "channelRequestMsg", + msgChannelSuccess: "channelRequestSuccessMsg", + msgChannelFailure: "channelRequestFailureMsg", +} diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go new file mode 100644 index 00000000..9654c018 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mux.go @@ -0,0 +1,351 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "encoding/binary" + "fmt" + "io" + "log" + "sync" + "sync/atomic" +) + +// debugMux, if set, causes messages in the connection protocol to be +// logged. +const debugMux = false + +// chanList is a thread safe channel list. +type chanList struct { + // protects concurrent access to chans + sync.Mutex + + // chans are indexed by the local id of the channel, which the + // other side should send in the PeersId field. + chans []*channel + + // This is a debugging aid: it offsets all IDs by this + // amount. This helps distinguish otherwise identical + // server/client muxes + offset uint32 +} + +// Assigns a channel ID to the given channel. +func (c *chanList) add(ch *channel) uint32 { + c.Lock() + defer c.Unlock() + for i := range c.chans { + if c.chans[i] == nil { + c.chans[i] = ch + return uint32(i) + c.offset + } + } + c.chans = append(c.chans, ch) + return uint32(len(c.chans)-1) + c.offset +} + +// getChan returns the channel for the given ID. +func (c *chanList) getChan(id uint32) *channel { + id -= c.offset + + c.Lock() + defer c.Unlock() + if id < uint32(len(c.chans)) { + return c.chans[id] + } + return nil +} + +func (c *chanList) remove(id uint32) { + id -= c.offset + c.Lock() + if id < uint32(len(c.chans)) { + c.chans[id] = nil + } + c.Unlock() +} + +// dropAll forgets all channels it knows, returning them in a slice. +func (c *chanList) dropAll() []*channel { + c.Lock() + defer c.Unlock() + var r []*channel + + for _, ch := range c.chans { + if ch == nil { + continue + } + r = append(r, ch) + } + c.chans = nil + return r +} + +// mux represents the state for the SSH connection protocol, which +// multiplexes many channels onto a single packet transport. +type mux struct { + conn packetConn + chanList chanList + + incomingChannels chan NewChannel + + globalSentMu sync.Mutex + globalResponses chan interface{} + incomingRequests chan *Request + + errCond *sync.Cond + err error +} + +// When debugging, each new chanList instantiation has a different +// offset. +var globalOff uint32 + +func (m *mux) Wait() error { + m.errCond.L.Lock() + defer m.errCond.L.Unlock() + for m.err == nil { + m.errCond.Wait() + } + return m.err +} + +// newMux returns a mux that runs over the given connection. +func newMux(p packetConn) *mux { + m := &mux{ + conn: p, + incomingChannels: make(chan NewChannel, chanSize), + globalResponses: make(chan interface{}, 1), + incomingRequests: make(chan *Request, chanSize), + errCond: newCond(), + } + if debugMux { + m.chanList.offset = atomic.AddUint32(&globalOff, 1) + } + + go m.loop() + return m +} + +func (m *mux) sendMessage(msg interface{}) error { + p := Marshal(msg) + if debugMux { + log.Printf("send global(%d): %#v", m.chanList.offset, msg) + } + return m.conn.writePacket(p) +} + +func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { + if wantReply { + m.globalSentMu.Lock() + defer m.globalSentMu.Unlock() + } + + if err := m.sendMessage(globalRequestMsg{ + Type: name, + WantReply: wantReply, + Data: payload, + }); err != nil { + return false, nil, err + } + + if !wantReply { + return false, nil, nil + } + + msg, ok := <-m.globalResponses + if !ok { + return false, nil, io.EOF + } + switch msg := msg.(type) { + case *globalRequestFailureMsg: + return false, msg.Data, nil + case *globalRequestSuccessMsg: + return true, msg.Data, nil + default: + return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) + } +} + +// ackRequest must be called after processing a global request that +// has WantReply set. +func (m *mux) ackRequest(ok bool, data []byte) error { + if ok { + return m.sendMessage(globalRequestSuccessMsg{Data: data}) + } + return m.sendMessage(globalRequestFailureMsg{Data: data}) +} + +func (m *mux) Close() error { + return m.conn.Close() +} + +// loop runs the connection machine. It will process packets until an +// error is encountered. To synchronize on loop exit, use mux.Wait. +func (m *mux) loop() { + var err error + for err == nil { + err = m.onePacket() + } + + for _, ch := range m.chanList.dropAll() { + ch.close() + } + + close(m.incomingChannels) + close(m.incomingRequests) + close(m.globalResponses) + + m.conn.Close() + + m.errCond.L.Lock() + m.err = err + m.errCond.Broadcast() + m.errCond.L.Unlock() + + if debugMux { + log.Println("loop exit", err) + } +} + +// onePacket reads and processes one packet. +func (m *mux) onePacket() error { + packet, err := m.conn.readPacket() + if err != nil { + return err + } + + if debugMux { + if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { + log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) + } else { + p, _ := decode(packet) + log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) + } + } + + switch packet[0] { + case msgChannelOpen: + return m.handleChannelOpen(packet) + case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: + return m.handleGlobalPacket(packet) + } + + // assume a channel packet. + if len(packet) < 5 { + return parseError(packet[0]) + } + id := binary.BigEndian.Uint32(packet[1:]) + ch := m.chanList.getChan(id) + if ch == nil { + return m.handleUnknownChannelPacket(id, packet) + } + + return ch.handlePacket(packet) +} + +func (m *mux) handleGlobalPacket(packet []byte) error { + msg, err := decode(packet) + if err != nil { + return err + } + + switch msg := msg.(type) { + case *globalRequestMsg: + m.incomingRequests <- &Request{ + Type: msg.Type, + WantReply: msg.WantReply, + Payload: msg.Data, + mux: m, + } + case *globalRequestSuccessMsg, *globalRequestFailureMsg: + m.globalResponses <- msg + default: + panic(fmt.Sprintf("not a global message %#v", msg)) + } + + return nil +} + +// handleChannelOpen schedules a channel to be Accept()ed. +func (m *mux) handleChannelOpen(packet []byte) error { + var msg channelOpenMsg + if err := Unmarshal(packet, &msg); err != nil { + return err + } + + if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { + failMsg := channelOpenFailureMsg{ + PeersID: msg.PeersID, + Reason: ConnectionFailed, + Message: "invalid request", + Language: "en_US.UTF-8", + } + return m.sendMessage(failMsg) + } + + c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) + c.remoteId = msg.PeersID + c.maxRemotePayload = msg.MaxPacketSize + c.remoteWin.add(msg.PeersWindow) + m.incomingChannels <- c + return nil +} + +func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { + ch, err := m.openChannel(chanType, extra) + if err != nil { + return nil, nil, err + } + + return ch, ch.incomingRequests, nil +} + +func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { + ch := m.newChannel(chanType, channelOutbound, extra) + + ch.maxIncomingPayload = channelMaxPacket + + open := channelOpenMsg{ + ChanType: chanType, + PeersWindow: ch.myWindow, + MaxPacketSize: ch.maxIncomingPayload, + TypeSpecificData: extra, + PeersID: ch.localId, + } + if err := m.sendMessage(open); err != nil { + return nil, err + } + + switch msg := (<-ch.msg).(type) { + case *channelOpenConfirmMsg: + return ch, nil + case *channelOpenFailureMsg: + return nil, &OpenChannelError{msg.Reason, msg.Message} + default: + return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) + } +} + +func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) error { + msg, err := decode(packet) + if err != nil { + return err + } + + switch msg := msg.(type) { + // RFC 4254 section 5.4 says unrecognized channel requests should + // receive a failure response. + case *channelRequestMsg: + if msg.WantReply { + return m.sendMessage(channelRequestFailureMsg{ + PeersID: msg.PeersID, + }) + } + return nil + default: + return fmt.Errorf("ssh: invalid channel %d", id) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go new file mode 100644 index 00000000..70045bdf --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -0,0 +1,752 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "strings" +) + +// The Permissions type holds fine-grained permissions that are +// specific to a user or a specific authentication method for a user. +// The Permissions value for a successful authentication attempt is +// available in ServerConn, so it can be used to pass information from +// the user-authentication phase to the application layer. +type Permissions struct { + // CriticalOptions indicate restrictions to the default + // permissions, and are typically used in conjunction with + // user certificates. The standard for SSH certificates + // defines "force-command" (only allow the given command to + // execute) and "source-address" (only allow connections from + // the given address). The SSH package currently only enforces + // the "source-address" critical option. It is up to server + // implementations to enforce other critical options, such as + // "force-command", by checking them after the SSH handshake + // is successful. In general, SSH servers should reject + // connections that specify critical options that are unknown + // or not supported. + CriticalOptions map[string]string + + // Extensions are extra functionality that the server may + // offer on authenticated connections. Lack of support for an + // extension does not preclude authenticating a user. Common + // extensions are "permit-agent-forwarding", + // "permit-X11-forwarding". The Go SSH library currently does + // not act on any extension, and it is up to server + // implementations to honor them. Extensions can be used to + // pass data from the authentication callbacks to the server + // application layer. + Extensions map[string]string +} + +type GSSAPIWithMICConfig struct { + // AllowLogin, must be set, is called when gssapi-with-mic + // authentication is selected (RFC 4462 section 3). The srcName is from the + // results of the GSS-API authentication. The format is username@DOMAIN. + // GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions. + // This callback is called after the user identity is established with GSSAPI to decide if the user can login with + // which permissions. If the user is allowed to login, it should return a nil error. + AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error) + + // Server must be set. It's the implementation + // of the GSSAPIServer interface. See GSSAPIServer interface for details. + Server GSSAPIServer +} + +// ServerConfig holds server specific configuration data. +type ServerConfig struct { + // Config contains configuration shared between client and server. + Config + + hostKeys []Signer + + // NoClientAuth is true if clients are allowed to connect without + // authenticating. + NoClientAuth bool + + // MaxAuthTries specifies the maximum number of authentication attempts + // permitted per connection. If set to a negative number, the number of + // attempts are unlimited. If set to zero, the number of attempts are limited + // to 6. + MaxAuthTries int + + // PasswordCallback, if non-nil, is called when a user + // attempts to authenticate using a password. + PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) + + // PublicKeyCallback, if non-nil, is called when a client + // offers a public key for authentication. It must return a nil error + // if the given public key can be used to authenticate the + // given user. For example, see CertChecker.Authenticate. A + // call to this function does not guarantee that the key + // offered is in fact used to authenticate. To record any data + // depending on the public key, store it inside a + // Permissions.Extensions entry. + PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // KeyboardInteractiveCallback, if non-nil, is called when + // keyboard-interactive authentication is selected (RFC + // 4256). The client object's Challenge function should be + // used to query the user. The callback may offer multiple + // Challenge rounds. To avoid information leaks, the client + // should be presented a challenge even if the user is + // unknown. + KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) + + // AuthLogCallback, if non-nil, is called to log all authentication + // attempts. + AuthLogCallback func(conn ConnMetadata, method string, err error) + + // ServerVersion is the version identification string to announce in + // the public handshake. + // If empty, a reasonable default is used. + // Note that RFC 4253 section 4.2 requires that this string start with + // "SSH-2.0-". + ServerVersion string + + // BannerCallback, if present, is called and the return string is sent to + // the client after key exchange completed but before authentication. + BannerCallback func(conn ConnMetadata) string + + // GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used + // when gssapi-with-mic authentication is selected (RFC 4462 section 3). + GSSAPIWithMICConfig *GSSAPIWithMICConfig +} + +// AddHostKey adds a private key as a host key. If an existing host +// key exists with the same public key format, it is replaced. Each server +// config must have at least one host key. +func (s *ServerConfig) AddHostKey(key Signer) { + for i, k := range s.hostKeys { + if k.PublicKey().Type() == key.PublicKey().Type() { + s.hostKeys[i] = key + return + } + } + + s.hostKeys = append(s.hostKeys, key) +} + +// cachedPubKey contains the results of querying whether a public key is +// acceptable for a user. +type cachedPubKey struct { + user string + pubKeyData []byte + result error + perms *Permissions +} + +const maxCachedPubKeys = 16 + +// pubKeyCache caches tests for public keys. Since SSH clients +// will query whether a public key is acceptable before attempting to +// authenticate with it, we end up with duplicate queries for public +// key validity. The cache only applies to a single ServerConn. +type pubKeyCache struct { + keys []cachedPubKey +} + +// get returns the result for a given user/algo/key tuple. +func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { + for _, k := range c.keys { + if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) { + return k, true + } + } + return cachedPubKey{}, false +} + +// add adds the given tuple to the cache. +func (c *pubKeyCache) add(candidate cachedPubKey) { + if len(c.keys) < maxCachedPubKeys { + c.keys = append(c.keys, candidate) + } +} + +// ServerConn is an authenticated SSH connection, as seen from the +// server +type ServerConn struct { + Conn + + // If the succeeding authentication callback returned a + // non-nil Permissions pointer, it is stored here. + Permissions *Permissions +} + +// NewServerConn starts a new SSH server with c as the underlying +// transport. It starts with a handshake and, if the handshake is +// unsuccessful, it closes the connection and returns an error. The +// Request and NewChannel channels must be serviced, or the connection +// will hang. +// +// The returned error may be of type *ServerAuthError for +// authentication errors. +func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { + fullConf := *config + fullConf.SetDefaults() + if fullConf.MaxAuthTries == 0 { + fullConf.MaxAuthTries = 6 + } + // Check if the config contains any unsupported key exchanges + for _, kex := range fullConf.KeyExchanges { + if _, ok := serverForbiddenKexAlgos[kex]; ok { + return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex) + } + } + + s := &connection{ + sshConn: sshConn{conn: c}, + } + perms, err := s.serverHandshake(&fullConf) + if err != nil { + c.Close() + return nil, nil, nil, err + } + return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil +} + +// signAndMarshal signs the data with the appropriate algorithm, +// and serializes the result in SSH wire format. algo is the negotiate +// algorithm and may be a certificate type. +func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) { + sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) + if err != nil { + return nil, err + } + + return Marshal(sig), nil +} + +// handshake performs key exchange and user authentication. +func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) { + if len(config.hostKeys) == 0 { + return nil, errors.New("ssh: server has no host keys") + } + + if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && + config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil || + config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) { + return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if config.ServerVersion != "" { + s.serverVersion = []byte(config.ServerVersion) + } else { + s.serverVersion = []byte(packageVersion) + } + var err error + s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) + if err != nil { + return nil, err + } + + tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */) + s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config) + + if err := s.transport.waitSession(); err != nil { + return nil, err + } + + // We just did the key change, so the session ID is established. + s.sessionID = s.transport.getSessionID() + + var packet []byte + if packet, err = s.transport.readPacket(); err != nil { + return nil, err + } + + var serviceRequest serviceRequestMsg + if err = Unmarshal(packet, &serviceRequest); err != nil { + return nil, err + } + if serviceRequest.Service != serviceUserAuth { + return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating") + } + serviceAccept := serviceAcceptMsg{ + Service: serviceUserAuth, + } + if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil { + return nil, err + } + + perms, err := s.serverAuthenticate(config) + if err != nil { + return nil, err + } + s.mux = newMux(s.transport) + return perms, err +} + +func isAcceptableAlgo(algo string) bool { + switch algo { + case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519, + CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: + return true + } + return false +} + +func checkSourceAddress(addr net.Addr, sourceAddrs string) error { + if addr == nil { + return errors.New("ssh: no address known for client, but source-address match required") + } + + tcpAddr, ok := addr.(*net.TCPAddr) + if !ok { + return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) + } + + for _, sourceAddr := range strings.Split(sourceAddrs, ",") { + if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { + if allowedIP.Equal(tcpAddr.IP) { + return nil + } + } else { + _, ipNet, err := net.ParseCIDR(sourceAddr) + if err != nil { + return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) + } + + if ipNet.Contains(tcpAddr.IP) { + return nil + } + } + } + + return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) +} + +func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection, + sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) { + gssAPIServer := gssapiConfig.Server + defer gssAPIServer.DeleteSecContext() + var srcName string + for { + var ( + outToken []byte + needContinue bool + ) + outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken) + if err != nil { + return err, nil, nil + } + if len(outToken) != 0 { + if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{ + Token: outToken, + })); err != nil { + return nil, nil, err + } + } + if !needContinue { + break + } + packet, err := s.transport.readPacket() + if err != nil { + return nil, nil, err + } + userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} + if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { + return nil, nil, err + } + } + packet, err := s.transport.readPacket() + if err != nil { + return nil, nil, err + } + userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{} + if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil { + return nil, nil, err + } + mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method) + if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil { + return err, nil, nil + } + perms, authErr = gssapiConfig.AllowLogin(s, srcName) + return authErr, perms, nil +} + +// ServerAuthError represents server authentication errors and is +// sometimes returned by NewServerConn. It appends any authentication +// errors that may occur, and is returned if all of the authentication +// methods provided by the user failed to authenticate. +type ServerAuthError struct { + // Errors contains authentication errors returned by the authentication + // callback methods. The first entry is typically ErrNoAuth. + Errors []error +} + +func (l ServerAuthError) Error() string { + var errs []string + for _, err := range l.Errors { + errs = append(errs, err.Error()) + } + return "[" + strings.Join(errs, ", ") + "]" +} + +// ErrNoAuth is the error value returned if no +// authentication method has been passed yet. This happens as a normal +// part of the authentication loop, since the client first tries +// 'none' authentication to discover available methods. +// It is returned in ServerAuthError.Errors from NewServerConn. +var ErrNoAuth = errors.New("ssh: no auth passed yet") + +func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { + sessionID := s.transport.getSessionID() + var cache pubKeyCache + var perms *Permissions + + authFailures := 0 + var authErrs []error + var displayedBanner bool + +userAuthLoop: + for { + if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 { + discMsg := &disconnectMsg{ + Reason: 2, + Message: "too many authentication failures", + } + + if err := s.transport.writePacket(Marshal(discMsg)); err != nil { + return nil, err + } + + return nil, discMsg + } + + var userAuthReq userAuthRequestMsg + if packet, err := s.transport.readPacket(); err != nil { + if err == io.EOF { + return nil, &ServerAuthError{Errors: authErrs} + } + return nil, err + } else if err = Unmarshal(packet, &userAuthReq); err != nil { + return nil, err + } + + if userAuthReq.Service != serviceSSH { + return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) + } + + s.user = userAuthReq.User + + if !displayedBanner && config.BannerCallback != nil { + displayedBanner = true + msg := config.BannerCallback(s) + if msg != "" { + bannerMsg := &userAuthBannerMsg{ + Message: msg, + } + if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { + return nil, err + } + } + } + + perms = nil + authErr := ErrNoAuth + + switch userAuthReq.Method { + case "none": + if config.NoClientAuth { + authErr = nil + } + + // allow initial attempt of 'none' without penalty + if authFailures == 0 { + authFailures-- + } + case "password": + if config.PasswordCallback == nil { + authErr = errors.New("ssh: password auth not configured") + break + } + payload := userAuthReq.Payload + if len(payload) < 1 || payload[0] != 0 { + return nil, parseError(msgUserAuthRequest) + } + payload = payload[1:] + password, payload, ok := parseString(payload) + if !ok || len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + perms, authErr = config.PasswordCallback(s, password) + case "keyboard-interactive": + if config.KeyboardInteractiveCallback == nil { + authErr = errors.New("ssh: keyboard-interactive auth not configured") + break + } + + prompter := &sshClientKeyboardInteractive{s} + perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) + case "publickey": + if config.PublicKeyCallback == nil { + authErr = errors.New("ssh: publickey auth not configured") + break + } + payload := userAuthReq.Payload + if len(payload) < 1 { + return nil, parseError(msgUserAuthRequest) + } + isQuery := payload[0] == 0 + payload = payload[1:] + algoBytes, payload, ok := parseString(payload) + if !ok { + return nil, parseError(msgUserAuthRequest) + } + algo := string(algoBytes) + if !isAcceptableAlgo(algo) { + authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) + break + } + + pubKeyData, payload, ok := parseString(payload) + if !ok { + return nil, parseError(msgUserAuthRequest) + } + + pubKey, err := ParsePublicKey(pubKeyData) + if err != nil { + return nil, err + } + + candidate, ok := cache.get(s.user, pubKeyData) + if !ok { + candidate.user = s.user + candidate.pubKeyData = pubKeyData + candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) + if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { + candidate.result = checkSourceAddress( + s.RemoteAddr(), + candidate.perms.CriticalOptions[sourceAddressCriticalOption]) + } + cache.add(candidate) + } + + if isQuery { + // The client can query if the given public key + // would be okay. + + if len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + if candidate.result == nil { + okMsg := userAuthPubKeyOkMsg{ + Algo: algo, + PubKey: pubKeyData, + } + if err = s.transport.writePacket(Marshal(&okMsg)); err != nil { + return nil, err + } + continue userAuthLoop + } + authErr = candidate.result + } else { + sig, payload, ok := parseSignature(payload) + if !ok || len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + // Ensure the public key algo and signature algo + // are supported. Compare the private key + // algorithm name that corresponds to algo with + // sig.Format. This is usually the same, but + // for certs, the names differ. + if !isAcceptableAlgo(sig.Format) { + authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format) + break + } + if underlyingAlgo(algo) != sig.Format { + authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo) + break + } + + signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData) + + if err := pubKey.Verify(signedData, sig); err != nil { + return nil, err + } + + authErr = candidate.result + perms = candidate.perms + } + case "gssapi-with-mic": + if config.GSSAPIWithMICConfig == nil { + authErr = errors.New("ssh: gssapi-with-mic auth not configured") + break + } + gssapiConfig := config.GSSAPIWithMICConfig + userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload) + if err != nil { + return nil, parseError(msgUserAuthRequest) + } + // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication. + if userAuthRequestGSSAPI.N == 0 { + authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported") + break + } + var i uint32 + present := false + for i = 0; i < userAuthRequestGSSAPI.N; i++ { + if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) { + present = true + break + } + } + if !present { + authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism") + break + } + // Initial server response, see RFC 4462 section 3.3. + if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{ + SupportMech: krb5OID, + })); err != nil { + return nil, err + } + // Exchange token, see RFC 4462 section 3.4. + packet, err := s.transport.readPacket() + if err != nil { + return nil, err + } + userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} + if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { + return nil, err + } + authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID, + userAuthReq) + if err != nil { + return nil, err + } + default: + authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) + } + + authErrs = append(authErrs, authErr) + + if config.AuthLogCallback != nil { + config.AuthLogCallback(s, userAuthReq.Method, authErr) + } + + if authErr == nil { + break userAuthLoop + } + + authFailures++ + if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries { + // If we have hit the max attempts, don't bother sending the + // final SSH_MSG_USERAUTH_FAILURE message, since there are + // no more authentication methods which can be attempted, + // and this message may cause the client to re-attempt + // authentication while we send the disconnect message. + // Continue, and trigger the disconnect at the start of + // the loop. + // + // The SSH specification is somewhat confusing about this, + // RFC 4252 Section 5.1 requires each authentication failure + // be responded to with a respective SSH_MSG_USERAUTH_FAILURE + // message, but Section 4 says the server should disconnect + // after some number of attempts, but it isn't explicit which + // message should take precedence (i.e. should there be a failure + // message than a disconnect message, or if we are going to + // disconnect, should we only send that message.) + // + // Either way, OpenSSH disconnects immediately after the last + // failed authnetication attempt, and given they are typically + // considered the golden implementation it seems reasonable + // to match that behavior. + continue + } + + var failureMsg userAuthFailureMsg + if config.PasswordCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "password") + } + if config.PublicKeyCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "publickey") + } + if config.KeyboardInteractiveCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") + } + if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil && + config.GSSAPIWithMICConfig.AllowLogin != nil { + failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic") + } + + if len(failureMsg.Methods) == 0 { + return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil { + return nil, err + } + } + + if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil { + return nil, err + } + return perms, nil +} + +// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by +// asking the client on the other side of a ServerConn. +type sshClientKeyboardInteractive struct { + *connection +} + +func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) { + if len(questions) != len(echos) { + return nil, errors.New("ssh: echos and questions must have equal length") + } + + var prompts []byte + for i := range questions { + prompts = appendString(prompts, questions[i]) + prompts = appendBool(prompts, echos[i]) + } + + if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ + Name: name, + Instruction: instruction, + NumPrompts: uint32(len(questions)), + Prompts: prompts, + })); err != nil { + return nil, err + } + + packet, err := c.transport.readPacket() + if err != nil { + return nil, err + } + if packet[0] != msgUserAuthInfoResponse { + return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0]) + } + packet = packet[1:] + + n, packet, ok := parseUint32(packet) + if !ok || int(n) != len(questions) { + return nil, parseError(msgUserAuthInfoResponse) + } + + for i := uint32(0); i < n; i++ { + ans, rest, ok := parseString(packet) + if !ok { + return nil, parseError(msgUserAuthInfoResponse) + } + + answers = append(answers, string(ans)) + packet = rest + } + if len(packet) != 0 { + return nil, errors.New("ssh: junk at end of message") + } + + return answers, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go new file mode 100644 index 00000000..eca31a22 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/session.go @@ -0,0 +1,648 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +// Session implements an interactive session described in +// "RFC 4254, section 6". + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" + "sync" +) + +type Signal string + +// POSIX signals as listed in RFC 4254 Section 6.10. +const ( + SIGABRT Signal = "ABRT" + SIGALRM Signal = "ALRM" + SIGFPE Signal = "FPE" + SIGHUP Signal = "HUP" + SIGILL Signal = "ILL" + SIGINT Signal = "INT" + SIGKILL Signal = "KILL" + SIGPIPE Signal = "PIPE" + SIGQUIT Signal = "QUIT" + SIGSEGV Signal = "SEGV" + SIGTERM Signal = "TERM" + SIGUSR1 Signal = "USR1" + SIGUSR2 Signal = "USR2" +) + +var signals = map[Signal]int{ + SIGABRT: 6, + SIGALRM: 14, + SIGFPE: 8, + SIGHUP: 1, + SIGILL: 4, + SIGINT: 2, + SIGKILL: 9, + SIGPIPE: 13, + SIGQUIT: 3, + SIGSEGV: 11, + SIGTERM: 15, +} + +type TerminalModes map[uint8]uint32 + +// POSIX terminal mode flags as listed in RFC 4254 Section 8. +const ( + tty_OP_END = 0 + VINTR = 1 + VQUIT = 2 + VERASE = 3 + VKILL = 4 + VEOF = 5 + VEOL = 6 + VEOL2 = 7 + VSTART = 8 + VSTOP = 9 + VSUSP = 10 + VDSUSP = 11 + VREPRINT = 12 + VWERASE = 13 + VLNEXT = 14 + VFLUSH = 15 + VSWTCH = 16 + VSTATUS = 17 + VDISCARD = 18 + IGNPAR = 30 + PARMRK = 31 + INPCK = 32 + ISTRIP = 33 + INLCR = 34 + IGNCR = 35 + ICRNL = 36 + IUCLC = 37 + IXON = 38 + IXANY = 39 + IXOFF = 40 + IMAXBEL = 41 + IUTF8 = 42 // RFC 8160 + ISIG = 50 + ICANON = 51 + XCASE = 52 + ECHO = 53 + ECHOE = 54 + ECHOK = 55 + ECHONL = 56 + NOFLSH = 57 + TOSTOP = 58 + IEXTEN = 59 + ECHOCTL = 60 + ECHOKE = 61 + PENDIN = 62 + OPOST = 70 + OLCUC = 71 + ONLCR = 72 + OCRNL = 73 + ONOCR = 74 + ONLRET = 75 + CS7 = 90 + CS8 = 91 + PARENB = 92 + PARODD = 93 + TTY_OP_ISPEED = 128 + TTY_OP_OSPEED = 129 +) + +// A Session represents a connection to a remote command or shell. +type Session struct { + // Stdin specifies the remote process's standard input. + // If Stdin is nil, the remote process reads from an empty + // bytes.Buffer. + Stdin io.Reader + + // Stdout and Stderr specify the remote process's standard + // output and error. + // + // If either is nil, Run connects the corresponding file + // descriptor to an instance of ioutil.Discard. There is a + // fixed amount of buffering that is shared for the two streams. + // If either blocks it may eventually cause the remote + // command to block. + Stdout io.Writer + Stderr io.Writer + + ch Channel // the channel backing this session + started bool // true once Start, Run or Shell is invoked. + copyFuncs []func() error + errors chan error // one send per copyFunc + + // true if pipe method is active + stdinpipe, stdoutpipe, stderrpipe bool + + // stdinPipeWriter is non-nil if StdinPipe has not been called + // and Stdin was specified by the user; it is the write end of + // a pipe connecting Session.Stdin to the stdin channel. + stdinPipeWriter io.WriteCloser + + exitStatus chan error +} + +// SendRequest sends an out-of-band channel request on the SSH channel +// underlying the session. +func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { + return s.ch.SendRequest(name, wantReply, payload) +} + +func (s *Session) Close() error { + return s.ch.Close() +} + +// RFC 4254 Section 6.4. +type setenvRequest struct { + Name string + Value string +} + +// Setenv sets an environment variable that will be applied to any +// command executed by Shell or Run. +func (s *Session) Setenv(name, value string) error { + msg := setenvRequest{ + Name: name, + Value: value, + } + ok, err := s.ch.SendRequest("env", true, Marshal(&msg)) + if err == nil && !ok { + err = errors.New("ssh: setenv failed") + } + return err +} + +// RFC 4254 Section 6.2. +type ptyRequestMsg struct { + Term string + Columns uint32 + Rows uint32 + Width uint32 + Height uint32 + Modelist string +} + +// RequestPty requests the association of a pty with the session on the remote host. +func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error { + var tm []byte + for k, v := range termmodes { + kv := struct { + Key byte + Val uint32 + }{k, v} + + tm = append(tm, Marshal(&kv)...) + } + tm = append(tm, tty_OP_END) + req := ptyRequestMsg{ + Term: term, + Columns: uint32(w), + Rows: uint32(h), + Width: uint32(w * 8), + Height: uint32(h * 8), + Modelist: string(tm), + } + ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req)) + if err == nil && !ok { + err = errors.New("ssh: pty-req failed") + } + return err +} + +// RFC 4254 Section 6.5. +type subsystemRequestMsg struct { + Subsystem string +} + +// RequestSubsystem requests the association of a subsystem with the session on the remote host. +// A subsystem is a predefined command that runs in the background when the ssh session is initiated +func (s *Session) RequestSubsystem(subsystem string) error { + msg := subsystemRequestMsg{ + Subsystem: subsystem, + } + ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg)) + if err == nil && !ok { + err = errors.New("ssh: subsystem request failed") + } + return err +} + +// RFC 4254 Section 6.7. +type ptyWindowChangeMsg struct { + Columns uint32 + Rows uint32 + Width uint32 + Height uint32 +} + +// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns. +func (s *Session) WindowChange(h, w int) error { + req := ptyWindowChangeMsg{ + Columns: uint32(w), + Rows: uint32(h), + Width: uint32(w * 8), + Height: uint32(h * 8), + } + _, err := s.ch.SendRequest("window-change", false, Marshal(&req)) + return err +} + +// RFC 4254 Section 6.9. +type signalMsg struct { + Signal string +} + +// Signal sends the given signal to the remote process. +// sig is one of the SIG* constants. +func (s *Session) Signal(sig Signal) error { + msg := signalMsg{ + Signal: string(sig), + } + + _, err := s.ch.SendRequest("signal", false, Marshal(&msg)) + return err +} + +// RFC 4254 Section 6.5. +type execMsg struct { + Command string +} + +// Start runs cmd on the remote host. Typically, the remote +// server passes cmd to the shell for interpretation. +// A Session only accepts one call to Run, Start or Shell. +func (s *Session) Start(cmd string) error { + if s.started { + return errors.New("ssh: session already started") + } + req := execMsg{ + Command: cmd, + } + + ok, err := s.ch.SendRequest("exec", true, Marshal(&req)) + if err == nil && !ok { + err = fmt.Errorf("ssh: command %v failed", cmd) + } + if err != nil { + return err + } + return s.start() +} + +// Run runs cmd on the remote host. Typically, the remote +// server passes cmd to the shell for interpretation. +// A Session only accepts one call to Run, Start, Shell, Output, +// or CombinedOutput. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the remote server does not send an exit status, an error of type +// *ExitMissingError is returned. If the command completes +// unsuccessfully or is interrupted by a signal, the error is of type +// *ExitError. Other error types may be returned for I/O problems. +func (s *Session) Run(cmd string) error { + err := s.Start(cmd) + if err != nil { + return err + } + return s.Wait() +} + +// Output runs cmd on the remote host and returns its standard output. +func (s *Session) Output(cmd string) ([]byte, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + var b bytes.Buffer + s.Stdout = &b + err := s.Run(cmd) + return b.Bytes(), err +} + +type singleWriter struct { + b bytes.Buffer + mu sync.Mutex +} + +func (w *singleWriter) Write(p []byte) (int, error) { + w.mu.Lock() + defer w.mu.Unlock() + return w.b.Write(p) +} + +// CombinedOutput runs cmd on the remote host and returns its combined +// standard output and standard error. +func (s *Session) CombinedOutput(cmd string) ([]byte, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + if s.Stderr != nil { + return nil, errors.New("ssh: Stderr already set") + } + var b singleWriter + s.Stdout = &b + s.Stderr = &b + err := s.Run(cmd) + return b.b.Bytes(), err +} + +// Shell starts a login shell on the remote host. A Session only +// accepts one call to Run, Start, Shell, Output, or CombinedOutput. +func (s *Session) Shell() error { + if s.started { + return errors.New("ssh: session already started") + } + + ok, err := s.ch.SendRequest("shell", true, nil) + if err == nil && !ok { + return errors.New("ssh: could not start shell") + } + if err != nil { + return err + } + return s.start() +} + +func (s *Session) start() error { + s.started = true + + type F func(*Session) + for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} { + setupFd(s) + } + + s.errors = make(chan error, len(s.copyFuncs)) + for _, fn := range s.copyFuncs { + go func(fn func() error) { + s.errors <- fn() + }(fn) + } + return nil +} + +// Wait waits for the remote command to exit. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the remote server does not send an exit status, an error of type +// *ExitMissingError is returned. If the command completes +// unsuccessfully or is interrupted by a signal, the error is of type +// *ExitError. Other error types may be returned for I/O problems. +func (s *Session) Wait() error { + if !s.started { + return errors.New("ssh: session not started") + } + waitErr := <-s.exitStatus + + if s.stdinPipeWriter != nil { + s.stdinPipeWriter.Close() + } + var copyError error + for range s.copyFuncs { + if err := <-s.errors; err != nil && copyError == nil { + copyError = err + } + } + if waitErr != nil { + return waitErr + } + return copyError +} + +func (s *Session) wait(reqs <-chan *Request) error { + wm := Waitmsg{status: -1} + // Wait for msg channel to be closed before returning. + for msg := range reqs { + switch msg.Type { + case "exit-status": + wm.status = int(binary.BigEndian.Uint32(msg.Payload)) + case "exit-signal": + var sigval struct { + Signal string + CoreDumped bool + Error string + Lang string + } + if err := Unmarshal(msg.Payload, &sigval); err != nil { + return err + } + + // Must sanitize strings? + wm.signal = sigval.Signal + wm.msg = sigval.Error + wm.lang = sigval.Lang + default: + // This handles keepalives and matches + // OpenSSH's behaviour. + if msg.WantReply { + msg.Reply(false, nil) + } + } + } + if wm.status == 0 { + return nil + } + if wm.status == -1 { + // exit-status was never sent from server + if wm.signal == "" { + // signal was not sent either. RFC 4254 + // section 6.10 recommends against this + // behavior, but it is allowed, so we let + // clients handle it. + return &ExitMissingError{} + } + wm.status = 128 + if _, ok := signals[Signal(wm.signal)]; ok { + wm.status += signals[Signal(wm.signal)] + } + } + + return &ExitError{wm} +} + +// ExitMissingError is returned if a session is torn down cleanly, but +// the server sends no confirmation of the exit status. +type ExitMissingError struct{} + +func (e *ExitMissingError) Error() string { + return "wait: remote command exited without exit status or exit signal" +} + +func (s *Session) stdin() { + if s.stdinpipe { + return + } + var stdin io.Reader + if s.Stdin == nil { + stdin = new(bytes.Buffer) + } else { + r, w := io.Pipe() + go func() { + _, err := io.Copy(w, s.Stdin) + w.CloseWithError(err) + }() + stdin, s.stdinPipeWriter = r, w + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.ch, stdin) + if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF { + err = err1 + } + return err + }) +} + +func (s *Session) stdout() { + if s.stdoutpipe { + return + } + if s.Stdout == nil { + s.Stdout = ioutil.Discard + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.Stdout, s.ch) + return err + }) +} + +func (s *Session) stderr() { + if s.stderrpipe { + return + } + if s.Stderr == nil { + s.Stderr = ioutil.Discard + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.Stderr, s.ch.Stderr()) + return err + }) +} + +// sessionStdin reroutes Close to CloseWrite. +type sessionStdin struct { + io.Writer + ch Channel +} + +func (s *sessionStdin) Close() error { + return s.ch.CloseWrite() +} + +// StdinPipe returns a pipe that will be connected to the +// remote command's standard input when the command starts. +func (s *Session) StdinPipe() (io.WriteCloser, error) { + if s.Stdin != nil { + return nil, errors.New("ssh: Stdin already set") + } + if s.started { + return nil, errors.New("ssh: StdinPipe after process started") + } + s.stdinpipe = true + return &sessionStdin{s.ch, s.ch}, nil +} + +// StdoutPipe returns a pipe that will be connected to the +// remote command's standard output when the command starts. +// There is a fixed amount of buffering that is shared between +// stdout and stderr streams. If the StdoutPipe reader is +// not serviced fast enough it may eventually cause the +// remote command to block. +func (s *Session) StdoutPipe() (io.Reader, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + if s.started { + return nil, errors.New("ssh: StdoutPipe after process started") + } + s.stdoutpipe = true + return s.ch, nil +} + +// StderrPipe returns a pipe that will be connected to the +// remote command's standard error when the command starts. +// There is a fixed amount of buffering that is shared between +// stdout and stderr streams. If the StderrPipe reader is +// not serviced fast enough it may eventually cause the +// remote command to block. +func (s *Session) StderrPipe() (io.Reader, error) { + if s.Stderr != nil { + return nil, errors.New("ssh: Stderr already set") + } + if s.started { + return nil, errors.New("ssh: StderrPipe after process started") + } + s.stderrpipe = true + return s.ch.Stderr(), nil +} + +// newSession returns a new interactive session on the remote host. +func newSession(ch Channel, reqs <-chan *Request) (*Session, error) { + s := &Session{ + ch: ch, + } + s.exitStatus = make(chan error, 1) + go func() { + s.exitStatus <- s.wait(reqs) + }() + + return s, nil +} + +// An ExitError reports unsuccessful completion of a remote command. +type ExitError struct { + Waitmsg +} + +func (e *ExitError) Error() string { + return e.Waitmsg.String() +} + +// Waitmsg stores the information about an exited remote command +// as reported by Wait. +type Waitmsg struct { + status int + signal string + msg string + lang string +} + +// ExitStatus returns the exit status of the remote command. +func (w Waitmsg) ExitStatus() int { + return w.status +} + +// Signal returns the exit signal of the remote command if +// it was terminated violently. +func (w Waitmsg) Signal() string { + return w.signal +} + +// Msg returns the exit message given by the remote command +func (w Waitmsg) Msg() string { + return w.msg +} + +// Lang returns the language tag. See RFC 3066 +func (w Waitmsg) Lang() string { + return w.lang +} + +func (w Waitmsg) String() string { + str := fmt.Sprintf("Process exited with status %v", w.status) + if w.signal != "" { + str += fmt.Sprintf(" from signal %v", w.signal) + } + if w.msg != "" { + str += fmt.Sprintf(". Reason was: %v", w.msg) + } + return str +} diff --git a/vendor/golang.org/x/crypto/ssh/ssh_gss.go b/vendor/golang.org/x/crypto/ssh/ssh_gss.go new file mode 100644 index 00000000..24bd7c8e --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/ssh_gss.go @@ -0,0 +1,139 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "encoding/asn1" + "errors" +) + +var krb5OID []byte + +func init() { + krb5OID, _ = asn1.Marshal(krb5Mesh) +} + +// GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins. +type GSSAPIClient interface { + // InitSecContext initiates the establishment of a security context for GSS-API between the + // ssh client and ssh server. Initially the token parameter should be specified as nil. + // The routine may return a outputToken which should be transferred to + // the ssh server, where the ssh server will present it to + // AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting + // needContinue to false. To complete the context + // establishment, one or more reply tokens may be required from the ssh + // server;if so, InitSecContext will return a needContinue which is true. + // In this case, InitSecContext should be called again when the + // reply token is received from the ssh server, passing the reply + // token to InitSecContext via the token parameters. + // See RFC 2743 section 2.2.1 and RFC 4462 section 3.4. + InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) + // GetMIC generates a cryptographic MIC for the SSH2 message, and places + // the MIC in a token for transfer to the ssh server. + // The contents of the MIC field are obtained by calling GSS_GetMIC() + // over the following, using the GSS-API context that was just + // established: + // string session identifier + // byte SSH_MSG_USERAUTH_REQUEST + // string user name + // string service + // string "gssapi-with-mic" + // See RFC 2743 section 2.3.1 and RFC 4462 3.5. + GetMIC(micFiled []byte) ([]byte, error) + // Whenever possible, it should be possible for + // DeleteSecContext() calls to be successfully processed even + // if other calls cannot succeed, thereby enabling context-related + // resources to be released. + // In addition to deleting established security contexts, + // gss_delete_sec_context must also be able to delete "half-built" + // security contexts resulting from an incomplete sequence of + // InitSecContext()/AcceptSecContext() calls. + // See RFC 2743 section 2.2.3. + DeleteSecContext() error +} + +// GSSAPIServer provides the API to plug in GSSAPI authentication for server logins. +type GSSAPIServer interface { + // AcceptSecContext allows a remotely initiated security context between the application + // and a remote peer to be established by the ssh client. The routine may return a + // outputToken which should be transferred to the ssh client, + // where the ssh client will present it to InitSecContext. + // If no token need be sent, AcceptSecContext will indicate this + // by setting the needContinue to false. To + // complete the context establishment, one or more reply tokens may be + // required from the ssh client. if so, AcceptSecContext + // will return a needContinue which is true, in which case it + // should be called again when the reply token is received from the ssh + // client, passing the token to AcceptSecContext via the + // token parameters. + // The srcName return value is the authenticated username. + // See RFC 2743 section 2.2.2 and RFC 4462 section 3.4. + AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) + // VerifyMIC verifies that a cryptographic MIC, contained in the token parameter, + // fits the supplied message is received from the ssh client. + // See RFC 2743 section 2.3.2. + VerifyMIC(micField []byte, micToken []byte) error + // Whenever possible, it should be possible for + // DeleteSecContext() calls to be successfully processed even + // if other calls cannot succeed, thereby enabling context-related + // resources to be released. + // In addition to deleting established security contexts, + // gss_delete_sec_context must also be able to delete "half-built" + // security contexts resulting from an incomplete sequence of + // InitSecContext()/AcceptSecContext() calls. + // See RFC 2743 section 2.2.3. + DeleteSecContext() error +} + +var ( + // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication, + // so we also support the krb5 mechanism only. + // See RFC 1964 section 1. + krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2} +) + +// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST +// See RFC 4462 section 3.2. +type userAuthRequestGSSAPI struct { + N uint32 + OIDS []asn1.ObjectIdentifier +} + +func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) { + n, rest, ok := parseUint32(payload) + if !ok { + return nil, errors.New("parse uint32 failed") + } + s := &userAuthRequestGSSAPI{ + N: n, + OIDS: make([]asn1.ObjectIdentifier, n), + } + for i := 0; i < int(n); i++ { + var ( + desiredMech []byte + err error + ) + desiredMech, rest, ok = parseString(rest) + if !ok { + return nil, errors.New("parse string failed") + } + if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil { + return nil, err + } + + } + return s, nil +} + +// See RFC 4462 section 3.6. +func buildMIC(sessionID string, username string, service string, authMethod string) []byte { + out := make([]byte, 0, 0) + out = appendString(out, sessionID) + out = append(out, msgUserAuthRequest) + out = appendString(out, username) + out = appendString(out, service) + out = appendString(out, authMethod) + return out +} diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go new file mode 100644 index 00000000..b171b330 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go @@ -0,0 +1,116 @@ +package ssh + +import ( + "errors" + "io" + "net" +) + +// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message +// with "direct-streamlocal@openssh.com" string. +// +// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding +// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235 +type streamLocalChannelOpenDirectMsg struct { + socketPath string + reserved0 string + reserved1 uint32 +} + +// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message +// with "forwarded-streamlocal@openssh.com" string. +type forwardedStreamLocalPayload struct { + SocketPath string + Reserved0 string +} + +// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message +// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string. +type streamLocalChannelForwardMsg struct { + socketPath string +} + +// ListenUnix is similar to ListenTCP but uses a Unix domain socket. +func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { + c.handleForwardsOnce.Do(c.handleForwards) + m := streamLocalChannelForwardMsg{ + socketPath, + } + // send message + ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m)) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer") + } + ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"}) + + return &unixListener{socketPath, c, ch}, nil +} + +func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { + msg := streamLocalChannelOpenDirectMsg{ + socketPath: socketPath, + } + ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg)) + if err != nil { + return nil, err + } + go DiscardRequests(in) + return ch, err +} + +type unixListener struct { + socketPath string + + conn *Client + in <-chan forward +} + +// Accept waits for and returns the next connection to the listener. +func (l *unixListener) Accept() (net.Conn, error) { + s, ok := <-l.in + if !ok { + return nil, io.EOF + } + ch, incoming, err := s.newCh.Accept() + if err != nil { + return nil, err + } + go DiscardRequests(incoming) + + return &chanConn{ + Channel: ch, + laddr: &net.UnixAddr{ + Name: l.socketPath, + Net: "unix", + }, + raddr: &net.UnixAddr{ + Name: "@", + Net: "unix", + }, + }, nil +} + +// Close closes the listener. +func (l *unixListener) Close() error { + // this also closes the listener. + l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"}) + m := streamLocalChannelForwardMsg{ + l.socketPath, + } + ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m)) + if err == nil && !ok { + err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed") + } + return err +} + +// Addr returns the listener's network address. +func (l *unixListener) Addr() net.Addr { + return &net.UnixAddr{ + Name: l.socketPath, + Net: "unix", + } +} diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go new file mode 100644 index 00000000..80d35f5e --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -0,0 +1,474 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "errors" + "fmt" + "io" + "math/rand" + "net" + "strconv" + "strings" + "sync" + "time" +) + +// Listen requests the remote peer open a listening socket on +// addr. Incoming connections will be available by calling Accept on +// the returned net.Listener. The listener must be serviced, or the +// SSH connection may hang. +// N must be "tcp", "tcp4", "tcp6", or "unix". +func (c *Client) Listen(n, addr string) (net.Listener, error) { + switch n { + case "tcp", "tcp4", "tcp6": + laddr, err := net.ResolveTCPAddr(n, addr) + if err != nil { + return nil, err + } + return c.ListenTCP(laddr) + case "unix": + return c.ListenUnix(addr) + default: + return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) + } +} + +// Automatic port allocation is broken with OpenSSH before 6.0. See +// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In +// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, +// rather than the actual port number. This means you can never open +// two different listeners with auto allocated ports. We work around +// this by trying explicit ports until we succeed. + +const openSSHPrefix = "OpenSSH_" + +var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) + +// isBrokenOpenSSHVersion returns true if the given version string +// specifies a version of OpenSSH that is known to have a bug in port +// forwarding. +func isBrokenOpenSSHVersion(versionStr string) bool { + i := strings.Index(versionStr, openSSHPrefix) + if i < 0 { + return false + } + i += len(openSSHPrefix) + j := i + for ; j < len(versionStr); j++ { + if versionStr[j] < '0' || versionStr[j] > '9' { + break + } + } + version, _ := strconv.Atoi(versionStr[i:j]) + return version < 6 +} + +// autoPortListenWorkaround simulates automatic port allocation by +// trying random ports repeatedly. +func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { + var sshListener net.Listener + var err error + const tries = 10 + for i := 0; i < tries; i++ { + addr := *laddr + addr.Port = 1024 + portRandomizer.Intn(60000) + sshListener, err = c.ListenTCP(&addr) + if err == nil { + laddr.Port = addr.Port + return sshListener, err + } + } + return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) +} + +// RFC 4254 7.1 +type channelForwardMsg struct { + addr string + rport uint32 +} + +// handleForwards starts goroutines handling forwarded connections. +// It's called on first use by (*Client).ListenTCP to not launch +// goroutines until needed. +func (c *Client) handleForwards() { + go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip")) + go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com")) +} + +// ListenTCP requests the remote peer open a listening socket +// on laddr. Incoming connections will be available by calling +// Accept on the returned net.Listener. +func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { + c.handleForwardsOnce.Do(c.handleForwards) + if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { + return c.autoPortListenWorkaround(laddr) + } + + m := channelForwardMsg{ + laddr.IP.String(), + uint32(laddr.Port), + } + // send message + ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("ssh: tcpip-forward request denied by peer") + } + + // If the original port was 0, then the remote side will + // supply a real port number in the response. + if laddr.Port == 0 { + var p struct { + Port uint32 + } + if err := Unmarshal(resp, &p); err != nil { + return nil, err + } + laddr.Port = int(p.Port) + } + + // Register this forward, using the port number we obtained. + ch := c.forwards.add(laddr) + + return &tcpListener{laddr, c, ch}, nil +} + +// forwardList stores a mapping between remote +// forward requests and the tcpListeners. +type forwardList struct { + sync.Mutex + entries []forwardEntry +} + +// forwardEntry represents an established mapping of a laddr on a +// remote ssh server to a channel connected to a tcpListener. +type forwardEntry struct { + laddr net.Addr + c chan forward +} + +// forward represents an incoming forwarded tcpip connection. The +// arguments to add/remove/lookup should be address as specified in +// the original forward-request. +type forward struct { + newCh NewChannel // the ssh client channel underlying this forward + raddr net.Addr // the raddr of the incoming connection +} + +func (l *forwardList) add(addr net.Addr) chan forward { + l.Lock() + defer l.Unlock() + f := forwardEntry{ + laddr: addr, + c: make(chan forward, 1), + } + l.entries = append(l.entries, f) + return f.c +} + +// See RFC 4254, section 7.2 +type forwardedTCPPayload struct { + Addr string + Port uint32 + OriginAddr string + OriginPort uint32 +} + +// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. +func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { + if port == 0 || port > 65535 { + return nil, fmt.Errorf("ssh: port number out of range: %d", port) + } + ip := net.ParseIP(string(addr)) + if ip == nil { + return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) + } + return &net.TCPAddr{IP: ip, Port: int(port)}, nil +} + +func (l *forwardList) handleChannels(in <-chan NewChannel) { + for ch := range in { + var ( + laddr net.Addr + raddr net.Addr + err error + ) + switch channelType := ch.ChannelType(); channelType { + case "forwarded-tcpip": + var payload forwardedTCPPayload + if err = Unmarshal(ch.ExtraData(), &payload); err != nil { + ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) + continue + } + + // RFC 4254 section 7.2 specifies that incoming + // addresses should list the address, in string + // format. It is implied that this should be an IP + // address, as it would be impossible to connect to it + // otherwise. + laddr, err = parseTCPAddr(payload.Addr, payload.Port) + if err != nil { + ch.Reject(ConnectionFailed, err.Error()) + continue + } + raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort) + if err != nil { + ch.Reject(ConnectionFailed, err.Error()) + continue + } + + case "forwarded-streamlocal@openssh.com": + var payload forwardedStreamLocalPayload + if err = Unmarshal(ch.ExtraData(), &payload); err != nil { + ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error()) + continue + } + laddr = &net.UnixAddr{ + Name: payload.SocketPath, + Net: "unix", + } + raddr = &net.UnixAddr{ + Name: "@", + Net: "unix", + } + default: + panic(fmt.Errorf("ssh: unknown channel type %s", channelType)) + } + if ok := l.forward(laddr, raddr, ch); !ok { + // Section 7.2, implementations MUST reject spurious incoming + // connections. + ch.Reject(Prohibited, "no forward for address") + continue + } + + } +} + +// remove removes the forward entry, and the channel feeding its +// listener. +func (l *forwardList) remove(addr net.Addr) { + l.Lock() + defer l.Unlock() + for i, f := range l.entries { + if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() { + l.entries = append(l.entries[:i], l.entries[i+1:]...) + close(f.c) + return + } + } +} + +// closeAll closes and clears all forwards. +func (l *forwardList) closeAll() { + l.Lock() + defer l.Unlock() + for _, f := range l.entries { + close(f.c) + } + l.entries = nil +} + +func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool { + l.Lock() + defer l.Unlock() + for _, f := range l.entries { + if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() { + f.c <- forward{newCh: ch, raddr: raddr} + return true + } + } + return false +} + +type tcpListener struct { + laddr *net.TCPAddr + + conn *Client + in <-chan forward +} + +// Accept waits for and returns the next connection to the listener. +func (l *tcpListener) Accept() (net.Conn, error) { + s, ok := <-l.in + if !ok { + return nil, io.EOF + } + ch, incoming, err := s.newCh.Accept() + if err != nil { + return nil, err + } + go DiscardRequests(incoming) + + return &chanConn{ + Channel: ch, + laddr: l.laddr, + raddr: s.raddr, + }, nil +} + +// Close closes the listener. +func (l *tcpListener) Close() error { + m := channelForwardMsg{ + l.laddr.IP.String(), + uint32(l.laddr.Port), + } + + // this also closes the listener. + l.conn.forwards.remove(l.laddr) + ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) + if err == nil && !ok { + err = errors.New("ssh: cancel-tcpip-forward failed") + } + return err +} + +// Addr returns the listener's network address. +func (l *tcpListener) Addr() net.Addr { + return l.laddr +} + +// Dial initiates a connection to the addr from the remote host. +// The resulting connection has a zero LocalAddr() and RemoteAddr(). +func (c *Client) Dial(n, addr string) (net.Conn, error) { + var ch Channel + switch n { + case "tcp", "tcp4", "tcp6": + // Parse the address into host and numeric port. + host, portString, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + port, err := strconv.ParseUint(portString, 10, 16) + if err != nil { + return nil, err + } + ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port)) + if err != nil { + return nil, err + } + // Use a zero address for local and remote address. + zeroAddr := &net.TCPAddr{ + IP: net.IPv4zero, + Port: 0, + } + return &chanConn{ + Channel: ch, + laddr: zeroAddr, + raddr: zeroAddr, + }, nil + case "unix": + var err error + ch, err = c.dialStreamLocal(addr) + if err != nil { + return nil, err + } + return &chanConn{ + Channel: ch, + laddr: &net.UnixAddr{ + Name: "@", + Net: "unix", + }, + raddr: &net.UnixAddr{ + Name: addr, + Net: "unix", + }, + }, nil + default: + return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) + } +} + +// DialTCP connects to the remote address raddr on the network net, +// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used +// as the local address for the connection. +func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { + if laddr == nil { + laddr = &net.TCPAddr{ + IP: net.IPv4zero, + Port: 0, + } + } + ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) + if err != nil { + return nil, err + } + return &chanConn{ + Channel: ch, + laddr: laddr, + raddr: raddr, + }, nil +} + +// RFC 4254 7.2 +type channelOpenDirectMsg struct { + raddr string + rport uint32 + laddr string + lport uint32 +} + +func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { + msg := channelOpenDirectMsg{ + raddr: raddr, + rport: uint32(rport), + laddr: laddr, + lport: uint32(lport), + } + ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) + if err != nil { + return nil, err + } + go DiscardRequests(in) + return ch, err +} + +type tcpChan struct { + Channel // the backing channel +} + +// chanConn fulfills the net.Conn interface without +// the tcpChan having to hold laddr or raddr directly. +type chanConn struct { + Channel + laddr, raddr net.Addr +} + +// LocalAddr returns the local network address. +func (t *chanConn) LocalAddr() net.Addr { + return t.laddr +} + +// RemoteAddr returns the remote network address. +func (t *chanConn) RemoteAddr() net.Addr { + return t.raddr +} + +// SetDeadline sets the read and write deadlines associated +// with the connection. +func (t *chanConn) SetDeadline(deadline time.Time) error { + if err := t.SetReadDeadline(deadline); err != nil { + return err + } + return t.SetWriteDeadline(deadline) +} + +// SetReadDeadline sets the read deadline. +// A zero value for t means Read will not time out. +// After the deadline, the error from Read will implement net.Error +// with Timeout() == true. +func (t *chanConn) SetReadDeadline(deadline time.Time) error { + // for compatibility with previous version, + // the error message contains "tcpChan" + return errors.New("ssh: tcpChan: deadline not supported") +} + +// SetWriteDeadline exists to satisfy the net.Conn interface +// but is not implemented by this type. It always returns an error. +func (t *chanConn) SetWriteDeadline(deadline time.Time) error { + return errors.New("ssh: tcpChan: deadline not supported") +} diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go new file mode 100644 index 00000000..acf5a21b --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -0,0 +1,357 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "bufio" + "bytes" + "errors" + "io" + "log" +) + +// debugTransport if set, will print packet types as they go over the +// wire. No message decoding is done, to minimize the impact on timing. +const debugTransport = false + +const ( + gcmCipherID = "aes128-gcm@openssh.com" + aes128cbcID = "aes128-cbc" + tripledescbcID = "3des-cbc" +) + +// packetConn represents a transport that implements packet based +// operations. +type packetConn interface { + // Encrypt and send a packet of data to the remote peer. + writePacket(packet []byte) error + + // Read a packet from the connection. The read is blocking, + // i.e. if error is nil, then the returned byte slice is + // always non-empty. + readPacket() ([]byte, error) + + // Close closes the write-side of the connection. + Close() error +} + +// transport is the keyingTransport that implements the SSH packet +// protocol. +type transport struct { + reader connectionState + writer connectionState + + bufReader *bufio.Reader + bufWriter *bufio.Writer + rand io.Reader + isClient bool + io.Closer +} + +// packetCipher represents a combination of SSH encryption/MAC +// protocol. A single instance should be used for one direction only. +type packetCipher interface { + // writeCipherPacket encrypts the packet and writes it to w. The + // contents of the packet are generally scrambled. + writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error + + // readCipherPacket reads and decrypts a packet of data. The + // returned packet may be overwritten by future calls of + // readPacket. + readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error) +} + +// connectionState represents one side (read or write) of the +// connection. This is necessary because each direction has its own +// keys, and can even have its own algorithms +type connectionState struct { + packetCipher + seqNum uint32 + dir direction + pendingKeyChange chan packetCipher +} + +// prepareKeyChange sets up key material for a keychange. The key changes in +// both directions are triggered by reading and writing a msgNewKey packet +// respectively. +func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { + ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) + if err != nil { + return err + } + t.reader.pendingKeyChange <- ciph + + ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) + if err != nil { + return err + } + t.writer.pendingKeyChange <- ciph + + return nil +} + +func (t *transport) printPacket(p []byte, write bool) { + if len(p) == 0 { + return + } + who := "server" + if t.isClient { + who = "client" + } + what := "read" + if write { + what = "write" + } + + log.Println(what, who, p[0]) +} + +// Read and decrypt next packet. +func (t *transport) readPacket() (p []byte, err error) { + for { + p, err = t.reader.readPacket(t.bufReader) + if err != nil { + break + } + if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { + break + } + } + if debugTransport { + t.printPacket(p, false) + } + + return p, err +} + +func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { + packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) + s.seqNum++ + if err == nil && len(packet) == 0 { + err = errors.New("ssh: zero length packet") + } + + if len(packet) > 0 { + switch packet[0] { + case msgNewKeys: + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher + default: + return nil, errors.New("ssh: got bogus newkeys message") + } + + case msgDisconnect: + // Transform a disconnect message into an + // error. Since this is lowest level at which + // we interpret message types, doing it here + // ensures that we don't have to handle it + // elsewhere. + var msg disconnectMsg + if err := Unmarshal(packet, &msg); err != nil { + return nil, err + } + return nil, &msg + } + } + + // The packet may point to an internal buffer, so copy the + // packet out here. + fresh := make([]byte, len(packet)) + copy(fresh, packet) + + return fresh, err +} + +func (t *transport) writePacket(packet []byte) error { + if debugTransport { + t.printPacket(packet, true) + } + return t.writer.writePacket(t.bufWriter, t.rand, packet) +} + +func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { + changeKeys := len(packet) > 0 && packet[0] == msgNewKeys + + err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) + if err != nil { + return err + } + if err = w.Flush(); err != nil { + return err + } + s.seqNum++ + if changeKeys { + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher + default: + panic("ssh: no key material for msgNewKeys") + } + } + return err +} + +func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { + t := &transport{ + bufReader: bufio.NewReader(rwc), + bufWriter: bufio.NewWriter(rwc), + rand: rand, + reader: connectionState{ + packetCipher: &streamPacketCipher{cipher: noneCipher{}}, + pendingKeyChange: make(chan packetCipher, 1), + }, + writer: connectionState{ + packetCipher: &streamPacketCipher{cipher: noneCipher{}}, + pendingKeyChange: make(chan packetCipher, 1), + }, + Closer: rwc, + } + t.isClient = isClient + + if isClient { + t.reader.dir = serverKeys + t.writer.dir = clientKeys + } else { + t.reader.dir = clientKeys + t.writer.dir = serverKeys + } + + return t +} + +type direction struct { + ivTag []byte + keyTag []byte + macKeyTag []byte +} + +var ( + serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} + clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} +) + +// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as +// described in RFC 4253, section 6.4. direction should either be serverKeys +// (to setup server->client keys) or clientKeys (for client->server keys). +func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { + cipherMode := cipherModes[algs.Cipher] + + iv := make([]byte, cipherMode.ivSize) + key := make([]byte, cipherMode.keySize) + + generateKeyMaterial(iv, d.ivTag, kex) + generateKeyMaterial(key, d.keyTag, kex) + + var macKey []byte + if !aeadCiphers[algs.Cipher] { + macMode := macModes[algs.MAC] + macKey = make([]byte, macMode.keySize) + generateKeyMaterial(macKey, d.macKeyTag, kex) + } + + return cipherModes[algs.Cipher].create(key, iv, macKey, algs) +} + +// generateKeyMaterial fills out with key material generated from tag, K, H +// and sessionId, as specified in RFC 4253, section 7.2. +func generateKeyMaterial(out, tag []byte, r *kexResult) { + var digestsSoFar []byte + + h := r.Hash.New() + for len(out) > 0 { + h.Reset() + h.Write(r.K) + h.Write(r.H) + + if len(digestsSoFar) == 0 { + h.Write(tag) + h.Write(r.SessionID) + } else { + h.Write(digestsSoFar) + } + + digest := h.Sum(nil) + n := copy(out, digest) + out = out[n:] + if len(out) > 0 { + digestsSoFar = append(digestsSoFar, digest...) + } + } +} + +const packageVersion = "SSH-2.0-Go" + +// Sends and receives a version line. The versionLine string should +// be US ASCII, start with "SSH-2.0-", and should not include a +// newline. exchangeVersions returns the other side's version line. +func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { + // Contrary to the RFC, we do not ignore lines that don't + // start with "SSH-2.0-" to make the library usable with + // nonconforming servers. + for _, c := range versionLine { + // The spec disallows non US-ASCII chars, and + // specifically forbids null chars. + if c < 32 { + return nil, errors.New("ssh: junk character in version line") + } + } + if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { + return + } + + them, err = readVersion(rw) + return them, err +} + +// maxVersionStringBytes is the maximum number of bytes that we'll +// accept as a version string. RFC 4253 section 4.2 limits this at 255 +// chars +const maxVersionStringBytes = 255 + +// Read version string as specified by RFC 4253, section 4.2. +func readVersion(r io.Reader) ([]byte, error) { + versionString := make([]byte, 0, 64) + var ok bool + var buf [1]byte + + for length := 0; length < maxVersionStringBytes; length++ { + _, err := io.ReadFull(r, buf[:]) + if err != nil { + return nil, err + } + // The RFC says that the version should be terminated with \r\n + // but several SSH servers actually only send a \n. + if buf[0] == '\n' { + if !bytes.HasPrefix(versionString, []byte("SSH-")) { + // RFC 4253 says we need to ignore all version string lines + // except the one containing the SSH version (provided that + // all the lines do not exceed 255 bytes in total). + versionString = versionString[:0] + continue + } + ok = true + break + } + + // non ASCII chars are disallowed, but we are lenient, + // since Go doesn't use null-terminated strings. + + // The RFC allows a comment after a space, however, + // all of it (version and comments) goes into the + // session hash. + versionString = append(versionString, buf[0]) + } + + if !ok { + return nil, errors.New("ssh: overflow reading version string") + } + + // There might be a '\r' on the end which we should remove. + if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { + versionString = versionString[:len(versionString)-1] + } + return versionString, nil +} diff --git a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s new file mode 100644 index 00000000..db9171c2 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s @@ -0,0 +1,18 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc +// +build gc + +#include "textflag.h" + +// +// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go +// + +TEXT ·syscall6(SB),NOSPLIT,$0-88 + JMP syscall·syscall6(SB) + +TEXT ·rawSyscall6(SB),NOSPLIT,$0-88 + JMP syscall·rawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/cpu/byteorder.go b/vendor/golang.org/x/sys/cpu/byteorder.go new file mode 100644 index 00000000..271055be --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/byteorder.go @@ -0,0 +1,66 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "runtime" +) + +// byteOrder is a subset of encoding/binary.ByteOrder. +type byteOrder interface { + Uint32([]byte) uint32 + Uint64([]byte) uint64 +} + +type littleEndian struct{} +type bigEndian struct{} + +func (littleEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func (littleEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func (bigEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 +} + +func (bigEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + +// hostByteOrder returns littleEndian on little-endian machines and +// bigEndian on big-endian machines. +func hostByteOrder() byteOrder { + switch runtime.GOARCH { + case "386", "amd64", "amd64p32", + "alpha", + "arm", "arm64", + "loong64", + "mipsle", "mips64le", "mips64p32le", + "nios2", + "ppc64le", + "riscv", "riscv64", + "sh": + return littleEndian{} + case "armbe", "arm64be", + "m68k", + "mips", "mips64", "mips64p32", + "ppc", "ppc64", + "s390", "s390x", + "shbe", + "sparc", "sparc64": + return bigEndian{} + } + panic("unknown architecture") +} diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go new file mode 100644 index 00000000..83f112c4 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -0,0 +1,287 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cpu implements processor feature detection for +// various CPU architectures. +package cpu + +import ( + "os" + "strings" +) + +// Initialized reports whether the CPU features were initialized. +// +// For some GOOS/GOARCH combinations initialization of the CPU features depends +// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm +// Initialized will report false if reading the file fails. +var Initialized bool + +// CacheLinePad is used to pad structs to avoid false sharing. +type CacheLinePad struct{ _ [cacheLineSize]byte } + +// X86 contains the supported CPU features of the +// current X86/AMD64 platform. If the current platform +// is not X86/AMD64 then all feature flags are false. +// +// X86 is padded to avoid false sharing. Further the HasAVX +// and HasAVX2 are only set if the OS supports XMM and YMM +// registers in addition to the CPUID feature bit being set. +var X86 struct { + _ CacheLinePad + HasAES bool // AES hardware implementation (AES NI) + HasADX bool // Multi-precision add-carry instruction extensions + HasAVX bool // Advanced vector extension + HasAVX2 bool // Advanced vector extension 2 + HasAVX512 bool // Advanced vector extension 512 + HasAVX512F bool // Advanced vector extension 512 Foundation Instructions + HasAVX512CD bool // Advanced vector extension 512 Conflict Detection Instructions + HasAVX512ER bool // Advanced vector extension 512 Exponential and Reciprocal Instructions + HasAVX512PF bool // Advanced vector extension 512 Prefetch Instructions Instructions + HasAVX512VL bool // Advanced vector extension 512 Vector Length Extensions + HasAVX512BW bool // Advanced vector extension 512 Byte and Word Instructions + HasAVX512DQ bool // Advanced vector extension 512 Doubleword and Quadword Instructions + HasAVX512IFMA bool // Advanced vector extension 512 Integer Fused Multiply Add + HasAVX512VBMI bool // Advanced vector extension 512 Vector Byte Manipulation Instructions + HasAVX5124VNNIW bool // Advanced vector extension 512 Vector Neural Network Instructions Word variable precision + HasAVX5124FMAPS bool // Advanced vector extension 512 Fused Multiply Accumulation Packed Single precision + HasAVX512VPOPCNTDQ bool // Advanced vector extension 512 Double and quad word population count instructions + HasAVX512VPCLMULQDQ bool // Advanced vector extension 512 Vector carry-less multiply operations + HasAVX512VNNI bool // Advanced vector extension 512 Vector Neural Network Instructions + HasAVX512GFNI bool // Advanced vector extension 512 Galois field New Instructions + HasAVX512VAES bool // Advanced vector extension 512 Vector AES instructions + HasAVX512VBMI2 bool // Advanced vector extension 512 Vector Byte Manipulation Instructions 2 + HasAVX512BITALG bool // Advanced vector extension 512 Bit Algorithms + HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions + HasBMI1 bool // Bit manipulation instruction set 1 + HasBMI2 bool // Bit manipulation instruction set 2 + HasCX16 bool // Compare and exchange 16 Bytes + HasERMS bool // Enhanced REP for MOVSB and STOSB + HasFMA bool // Fused-multiply-add instructions + HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. + HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM + HasPOPCNT bool // Hamming weight instruction POPCNT. + HasRDRAND bool // RDRAND instruction (on-chip random number generator) + HasRDSEED bool // RDSEED instruction (on-chip random number generator) + HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) + HasSSE3 bool // Streaming SIMD extension 3 + HasSSSE3 bool // Supplemental streaming SIMD extension 3 + HasSSE41 bool // Streaming SIMD extension 4 and 4.1 + HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + _ CacheLinePad +} + +// ARM64 contains the supported CPU features of the +// current ARMv8(aarch64) platform. If the current platform +// is not arm64 then all feature flags are false. +var ARM64 struct { + _ CacheLinePad + HasFP bool // Floating-point instruction set (always available) + HasASIMD bool // Advanced SIMD (always available) + HasEVTSTRM bool // Event stream support + HasAES bool // AES hardware implementation + HasPMULL bool // Polynomial multiplication instruction set + HasSHA1 bool // SHA1 hardware implementation + HasSHA2 bool // SHA2 hardware implementation + HasCRC32 bool // CRC32 hardware implementation + HasATOMICS bool // Atomic memory operation instruction set + HasFPHP bool // Half precision floating-point instruction set + HasASIMDHP bool // Advanced SIMD half precision instruction set + HasCPUID bool // CPUID identification scheme registers + HasASIMDRDM bool // Rounding double multiply add/subtract instruction set + HasJSCVT bool // Javascript conversion from floating-point to integer + HasFCMA bool // Floating-point multiplication and addition of complex numbers + HasLRCPC bool // Release Consistent processor consistent support + HasDCPOP bool // Persistent memory support + HasSHA3 bool // SHA3 hardware implementation + HasSM3 bool // SM3 hardware implementation + HasSM4 bool // SM4 hardware implementation + HasASIMDDP bool // Advanced SIMD double precision instruction set + HasSHA512 bool // SHA512 hardware implementation + HasSVE bool // Scalable Vector Extensions + HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 + _ CacheLinePad +} + +// ARM contains the supported CPU features of the current ARM (32-bit) platform. +// All feature flags are false if: +// 1. the current platform is not arm, or +// 2. the current operating system is not Linux. +var ARM struct { + _ CacheLinePad + HasSWP bool // SWP instruction support + HasHALF bool // Half-word load and store support + HasTHUMB bool // ARM Thumb instruction set + Has26BIT bool // Address space limited to 26-bits + HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support + HasFPA bool // Floating point arithmetic support + HasVFP bool // Vector floating point support + HasEDSP bool // DSP Extensions support + HasJAVA bool // Java instruction set + HasIWMMXT bool // Intel Wireless MMX technology support + HasCRUNCH bool // MaverickCrunch context switching and handling + HasTHUMBEE bool // Thumb EE instruction set + HasNEON bool // NEON instruction set + HasVFPv3 bool // Vector floating point version 3 support + HasVFPv3D16 bool // Vector floating point version 3 D8-D15 + HasTLS bool // Thread local storage support + HasVFPv4 bool // Vector floating point version 4 support + HasIDIVA bool // Integer divide instruction support in ARM mode + HasIDIVT bool // Integer divide instruction support in Thumb mode + HasVFPD32 bool // Vector floating point version 3 D15-D31 + HasLPAE bool // Large Physical Address Extensions + HasEVTSTRM bool // Event stream support + HasAES bool // AES hardware implementation + HasPMULL bool // Polynomial multiplication instruction set + HasSHA1 bool // SHA1 hardware implementation + HasSHA2 bool // SHA2 hardware implementation + HasCRC32 bool // CRC32 hardware implementation + _ CacheLinePad +} + +// MIPS64X contains the supported CPU features of the current mips64/mips64le +// platforms. If the current platform is not mips64/mips64le or the current +// operating system is not Linux then all feature flags are false. +var MIPS64X struct { + _ CacheLinePad + HasMSA bool // MIPS SIMD architecture + _ CacheLinePad +} + +// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. +// If the current platform is not ppc64/ppc64le then all feature flags are false. +// +// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, +// since there are no optional categories. There are some exceptions that also +// require kernel support to work (DARN, SCV), so there are feature bits for +// those as well. The struct is padded to avoid false sharing. +var PPC64 struct { + _ CacheLinePad + HasDARN bool // Hardware random number generator (requires kernel enablement) + HasSCV bool // Syscall vectored (requires kernel enablement) + IsPOWER8 bool // ISA v2.07 (POWER8) + IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 + _ CacheLinePad +} + +// S390X contains the supported CPU features of the current IBM Z +// (s390x) platform. If the current platform is not IBM Z then all +// feature flags are false. +// +// S390X is padded to avoid false sharing. Further HasVX is only set +// if the OS supports vector registers in addition to the STFLE +// feature bit being set. +var S390X struct { + _ CacheLinePad + HasZARCH bool // z/Architecture mode is active [mandatory] + HasSTFLE bool // store facility list extended + HasLDISP bool // long (20-bit) displacements + HasEIMM bool // 32-bit immediates + HasDFP bool // decimal floating point + HasETF3EH bool // ETF-3 enhanced + HasMSA bool // message security assist (CPACF) + HasAES bool // KM-AES{128,192,256} functions + HasAESCBC bool // KMC-AES{128,192,256} functions + HasAESCTR bool // KMCTR-AES{128,192,256} functions + HasAESGCM bool // KMA-GCM-AES{128,192,256} functions + HasGHASH bool // KIMD-GHASH function + HasSHA1 bool // K{I,L}MD-SHA-1 functions + HasSHA256 bool // K{I,L}MD-SHA-256 functions + HasSHA512 bool // K{I,L}MD-SHA-512 functions + HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions + HasVX bool // vector facility + HasVXE bool // vector-enhancements facility 1 + _ CacheLinePad +} + +func init() { + archInit() + initOptions() + processOptions() +} + +// options contains the cpu debug options that can be used in GODEBUG. +// Options are arch dependent and are added by the arch specific initOptions functions. +// Features that are mandatory for the specific GOARCH should have the Required field set +// (e.g. SSE2 on amd64). +var options []option + +// Option names should be lower case. e.g. avx instead of AVX. +type option struct { + Name string + Feature *bool + Specified bool // whether feature value was specified in GODEBUG + Enable bool // whether feature should be enabled + Required bool // whether feature is mandatory and can not be disabled +} + +func processOptions() { + env := os.Getenv("GODEBUG") +field: + for env != "" { + field := "" + i := strings.IndexByte(env, ',') + if i < 0 { + field, env = env, "" + } else { + field, env = env[:i], env[i+1:] + } + if len(field) < 4 || field[:4] != "cpu." { + continue + } + i = strings.IndexByte(field, '=') + if i < 0 { + print("GODEBUG sys/cpu: no value specified for \"", field, "\"\n") + continue + } + key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" + + var enable bool + switch value { + case "on": + enable = true + case "off": + enable = false + default: + print("GODEBUG sys/cpu: value \"", value, "\" not supported for cpu option \"", key, "\"\n") + continue field + } + + if key == "all" { + for i := range options { + options[i].Specified = true + options[i].Enable = enable || options[i].Required + } + continue field + } + + for i := range options { + if options[i].Name == key { + options[i].Specified = true + options[i].Enable = enable + continue field + } + } + + print("GODEBUG sys/cpu: unknown cpu feature \"", key, "\"\n") + } + + for _, o := range options { + if !o.Specified { + continue + } + + if o.Enable && !*o.Feature { + print("GODEBUG sys/cpu: can not enable \"", o.Name, "\", missing CPU support\n") + continue + } + + if !o.Enable && o.Required { + print("GODEBUG sys/cpu: can not disable \"", o.Name, "\", required CPU feature\n") + continue + } + + *o.Feature = o.Enable + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_aix.go b/vendor/golang.org/x/sys/cpu/cpu_aix.go new file mode 100644 index 00000000..8aaeef54 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_aix.go @@ -0,0 +1,34 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix +// +build aix + +package cpu + +const ( + // getsystemcfg constants + _SC_IMPL = 2 + _IMPL_POWER8 = 0x10000 + _IMPL_POWER9 = 0x20000 +) + +func archInit() { + impl := getsystemcfg(_SC_IMPL) + if impl&_IMPL_POWER8 != 0 { + PPC64.IsPOWER8 = true + } + if impl&_IMPL_POWER9 != 0 { + PPC64.IsPOWER8 = true + PPC64.IsPOWER9 = true + } + + Initialized = true +} + +func getsystemcfg(label int) (n uint64) { + r0, _ := callgetsystemcfg(label) + n = uint64(r0) + return +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go new file mode 100644 index 00000000..301b752e --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm.go @@ -0,0 +1,73 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 32 + +// HWCAP/HWCAP2 bits. +// These are specific to Linux. +const ( + hwcap_SWP = 1 << 0 + hwcap_HALF = 1 << 1 + hwcap_THUMB = 1 << 2 + hwcap_26BIT = 1 << 3 + hwcap_FAST_MULT = 1 << 4 + hwcap_FPA = 1 << 5 + hwcap_VFP = 1 << 6 + hwcap_EDSP = 1 << 7 + hwcap_JAVA = 1 << 8 + hwcap_IWMMXT = 1 << 9 + hwcap_CRUNCH = 1 << 10 + hwcap_THUMBEE = 1 << 11 + hwcap_NEON = 1 << 12 + hwcap_VFPv3 = 1 << 13 + hwcap_VFPv3D16 = 1 << 14 + hwcap_TLS = 1 << 15 + hwcap_VFPv4 = 1 << 16 + hwcap_IDIVA = 1 << 17 + hwcap_IDIVT = 1 << 18 + hwcap_VFPD32 = 1 << 19 + hwcap_LPAE = 1 << 20 + hwcap_EVTSTRM = 1 << 21 + + hwcap2_AES = 1 << 0 + hwcap2_PMULL = 1 << 1 + hwcap2_SHA1 = 1 << 2 + hwcap2_SHA2 = 1 << 3 + hwcap2_CRC32 = 1 << 4 +) + +func initOptions() { + options = []option{ + {Name: "pmull", Feature: &ARM.HasPMULL}, + {Name: "sha1", Feature: &ARM.HasSHA1}, + {Name: "sha2", Feature: &ARM.HasSHA2}, + {Name: "swp", Feature: &ARM.HasSWP}, + {Name: "thumb", Feature: &ARM.HasTHUMB}, + {Name: "thumbee", Feature: &ARM.HasTHUMBEE}, + {Name: "tls", Feature: &ARM.HasTLS}, + {Name: "vfp", Feature: &ARM.HasVFP}, + {Name: "vfpd32", Feature: &ARM.HasVFPD32}, + {Name: "vfpv3", Feature: &ARM.HasVFPv3}, + {Name: "vfpv3d16", Feature: &ARM.HasVFPv3D16}, + {Name: "vfpv4", Feature: &ARM.HasVFPv4}, + {Name: "half", Feature: &ARM.HasHALF}, + {Name: "26bit", Feature: &ARM.Has26BIT}, + {Name: "fastmul", Feature: &ARM.HasFASTMUL}, + {Name: "fpa", Feature: &ARM.HasFPA}, + {Name: "edsp", Feature: &ARM.HasEDSP}, + {Name: "java", Feature: &ARM.HasJAVA}, + {Name: "iwmmxt", Feature: &ARM.HasIWMMXT}, + {Name: "crunch", Feature: &ARM.HasCRUNCH}, + {Name: "neon", Feature: &ARM.HasNEON}, + {Name: "idivt", Feature: &ARM.HasIDIVT}, + {Name: "idiva", Feature: &ARM.HasIDIVA}, + {Name: "lpae", Feature: &ARM.HasLPAE}, + {Name: "evtstrm", Feature: &ARM.HasEVTSTRM}, + {Name: "aes", Feature: &ARM.HasAES}, + {Name: "crc32", Feature: &ARM.HasCRC32}, + } + +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go new file mode 100644 index 00000000..87dd5e30 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -0,0 +1,172 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import "runtime" + +const cacheLineSize = 64 + +func initOptions() { + options = []option{ + {Name: "fp", Feature: &ARM64.HasFP}, + {Name: "asimd", Feature: &ARM64.HasASIMD}, + {Name: "evstrm", Feature: &ARM64.HasEVTSTRM}, + {Name: "aes", Feature: &ARM64.HasAES}, + {Name: "fphp", Feature: &ARM64.HasFPHP}, + {Name: "jscvt", Feature: &ARM64.HasJSCVT}, + {Name: "lrcpc", Feature: &ARM64.HasLRCPC}, + {Name: "pmull", Feature: &ARM64.HasPMULL}, + {Name: "sha1", Feature: &ARM64.HasSHA1}, + {Name: "sha2", Feature: &ARM64.HasSHA2}, + {Name: "sha3", Feature: &ARM64.HasSHA3}, + {Name: "sha512", Feature: &ARM64.HasSHA512}, + {Name: "sm3", Feature: &ARM64.HasSM3}, + {Name: "sm4", Feature: &ARM64.HasSM4}, + {Name: "sve", Feature: &ARM64.HasSVE}, + {Name: "crc32", Feature: &ARM64.HasCRC32}, + {Name: "atomics", Feature: &ARM64.HasATOMICS}, + {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, + {Name: "cpuid", Feature: &ARM64.HasCPUID}, + {Name: "asimrdm", Feature: &ARM64.HasASIMDRDM}, + {Name: "fcma", Feature: &ARM64.HasFCMA}, + {Name: "dcpop", Feature: &ARM64.HasDCPOP}, + {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, + {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, + } +} + +func archInit() { + switch runtime.GOOS { + case "freebsd": + readARM64Registers() + case "linux", "netbsd": + doinit() + default: + // Most platforms don't seem to allow reading these registers. + // + // OpenBSD: + // See https://golang.org/issue/31746 + setMinimalFeatures() + } +} + +// setMinimalFeatures fakes the minimal ARM64 features expected by +// TestARM64minimalFeatures. +func setMinimalFeatures() { + ARM64.HasASIMD = true + ARM64.HasFP = true +} + +func readARM64Registers() { + Initialized = true + + parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0()) +} + +func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { + // ID_AA64ISAR0_EL1 + switch extractBits(isar0, 4, 7) { + case 1: + ARM64.HasAES = true + case 2: + ARM64.HasAES = true + ARM64.HasPMULL = true + } + + switch extractBits(isar0, 8, 11) { + case 1: + ARM64.HasSHA1 = true + } + + switch extractBits(isar0, 12, 15) { + case 1: + ARM64.HasSHA2 = true + case 2: + ARM64.HasSHA2 = true + ARM64.HasSHA512 = true + } + + switch extractBits(isar0, 16, 19) { + case 1: + ARM64.HasCRC32 = true + } + + switch extractBits(isar0, 20, 23) { + case 2: + ARM64.HasATOMICS = true + } + + switch extractBits(isar0, 28, 31) { + case 1: + ARM64.HasASIMDRDM = true + } + + switch extractBits(isar0, 32, 35) { + case 1: + ARM64.HasSHA3 = true + } + + switch extractBits(isar0, 36, 39) { + case 1: + ARM64.HasSM3 = true + } + + switch extractBits(isar0, 40, 43) { + case 1: + ARM64.HasSM4 = true + } + + switch extractBits(isar0, 44, 47) { + case 1: + ARM64.HasASIMDDP = true + } + + // ID_AA64ISAR1_EL1 + switch extractBits(isar1, 0, 3) { + case 1: + ARM64.HasDCPOP = true + } + + switch extractBits(isar1, 12, 15) { + case 1: + ARM64.HasJSCVT = true + } + + switch extractBits(isar1, 16, 19) { + case 1: + ARM64.HasFCMA = true + } + + switch extractBits(isar1, 20, 23) { + case 1: + ARM64.HasLRCPC = true + } + + // ID_AA64PFR0_EL1 + switch extractBits(pfr0, 16, 19) { + case 0: + ARM64.HasFP = true + case 1: + ARM64.HasFP = true + ARM64.HasFPHP = true + } + + switch extractBits(pfr0, 20, 23) { + case 0: + ARM64.HasASIMD = true + case 1: + ARM64.HasASIMD = true + ARM64.HasASIMDHP = true + } + + switch extractBits(pfr0, 32, 35) { + case 1: + ARM64.HasSVE = true + } +} + +func extractBits(data uint64, start, end uint) uint { + return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s new file mode 100644 index 00000000..c61f95a0 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.s @@ -0,0 +1,32 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc +// +build gc + +#include "textflag.h" + +// func getisar0() uint64 +TEXT ·getisar0(SB),NOSPLIT,$0-8 + // get Instruction Set Attributes 0 into x0 + // mrs x0, ID_AA64ISAR0_EL1 = d5380600 + WORD $0xd5380600 + MOVD R0, ret+0(FP) + RET + +// func getisar1() uint64 +TEXT ·getisar1(SB),NOSPLIT,$0-8 + // get Instruction Set Attributes 1 into x0 + // mrs x0, ID_AA64ISAR1_EL1 = d5380620 + WORD $0xd5380620 + MOVD R0, ret+0(FP) + RET + +// func getpfr0() uint64 +TEXT ·getpfr0(SB),NOSPLIT,$0-8 + // get Processor Feature Register 0 into x0 + // mrs x0, ID_AA64PFR0_EL1 = d5380400 + WORD $0xd5380400 + MOVD R0, ret+0(FP) + RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go new file mode 100644 index 00000000..ccf542a7 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -0,0 +1,12 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc +// +build gc + +package cpu + +func getisar0() uint64 +func getisar1() uint64 +func getpfr0() uint64 diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go new file mode 100644 index 00000000..0af2f248 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc +// +build gc + +package cpu + +// haveAsmFunctions reports whether the other functions in this file can +// be safely called. +func haveAsmFunctions() bool { return true } + +// The following feature detection functions are defined in cpu_s390x.s. +// They are likely to be expensive to call so the results should be cached. +func stfle() facilityList +func kmQuery() queryResult +func kmcQuery() queryResult +func kmctrQuery() queryResult +func kmaQuery() queryResult +func kimdQuery() queryResult +func klmdQuery() queryResult diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go new file mode 100644 index 00000000..fa7cdb9b --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -0,0 +1,17 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (386 || amd64 || amd64p32) && gc +// +build 386 amd64 amd64p32 +// +build gc + +package cpu + +// cpuid is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) + +// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. +func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go new file mode 100644 index 00000000..2aff3189 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go @@ -0,0 +1,12 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gccgo +// +build gccgo + +package cpu + +func getisar0() uint64 { return 0 } +func getisar1() uint64 { return 0 } +func getpfr0() uint64 { return 0 } diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go new file mode 100644 index 00000000..4bfbda61 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go @@ -0,0 +1,23 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gccgo +// +build gccgo + +package cpu + +// haveAsmFunctions reports whether the other functions in this file can +// be safely called. +func haveAsmFunctions() bool { return false } + +// TODO(mundaym): the following feature detection functions are currently +// stubs. See https://golang.org/cl/162887 for how to fix this. +// They are likely to be expensive to call so the results should be cached. +func stfle() facilityList { panic("not implemented for gccgo") } +func kmQuery() queryResult { panic("not implemented for gccgo") } +func kmcQuery() queryResult { panic("not implemented for gccgo") } +func kmctrQuery() queryResult { panic("not implemented for gccgo") } +func kmaQuery() queryResult { panic("not implemented for gccgo") } +func kimdQuery() queryResult { panic("not implemented for gccgo") } +func klmdQuery() queryResult { panic("not implemented for gccgo") } diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c new file mode 100644 index 00000000..e363c7d1 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c @@ -0,0 +1,43 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +#include +#include + +// Need to wrap __get_cpuid_count because it's declared as static. +int +gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); +} + +// xgetbv reads the contents of an XCR (Extended Control Register) +// specified in the ECX register into registers EDX:EAX. +// Currently, the only supported value for XCR is 0. +// +// TODO: Replace with a better alternative: +// +// #include +// +// #pragma GCC target("xsave") +// +// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { +// unsigned long long x = _xgetbv(0); +// *eax = x & 0xffffffff; +// *edx = (x >> 32) & 0xffffffff; +// } +// +// Note that _xgetbv is defined starting with GCC 8. +void +gccgoXgetbv(uint32_t *eax, uint32_t *edx) +{ + __asm(" xorl %%ecx, %%ecx\n" + " xgetbv" + : "=a"(*eax), "=d"(*edx)); +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go new file mode 100644 index 00000000..863d415a --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (386 || amd64 || amd64p32) && gccgo +// +build 386 amd64 amd64p32 +// +build gccgo + +package cpu + +//extern gccgoGetCpuidCount +func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) + +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { + var a, b, c, d uint32 + gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) + return a, b, c, d +} + +//extern gccgoXgetbv +func gccgoXgetbv(eax, edx *uint32) + +func xgetbv() (eax, edx uint32) { + var a, d uint32 + gccgoXgetbv(&a, &d) + return a, d +} + +// gccgo doesn't build on Darwin, per: +// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76 +func darwinSupportsAVX512() bool { + return false +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux.go b/vendor/golang.org/x/sys/cpu/cpu_linux.go new file mode 100644 index 00000000..159a686f --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !386 && !amd64 && !amd64p32 && !arm64 +// +build !386,!amd64,!amd64p32,!arm64 + +package cpu + +func archInit() { + if err := readHWCAP(); err != nil { + return + } + doinit() + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go new file mode 100644 index 00000000..2057006d --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go @@ -0,0 +1,39 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +func doinit() { + ARM.HasSWP = isSet(hwCap, hwcap_SWP) + ARM.HasHALF = isSet(hwCap, hwcap_HALF) + ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB) + ARM.Has26BIT = isSet(hwCap, hwcap_26BIT) + ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT) + ARM.HasFPA = isSet(hwCap, hwcap_FPA) + ARM.HasVFP = isSet(hwCap, hwcap_VFP) + ARM.HasEDSP = isSet(hwCap, hwcap_EDSP) + ARM.HasJAVA = isSet(hwCap, hwcap_JAVA) + ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT) + ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH) + ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE) + ARM.HasNEON = isSet(hwCap, hwcap_NEON) + ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3) + ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16) + ARM.HasTLS = isSet(hwCap, hwcap_TLS) + ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4) + ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA) + ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT) + ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32) + ARM.HasLPAE = isSet(hwCap, hwcap_LPAE) + ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) + ARM.HasAES = isSet(hwCap2, hwcap2_AES) + ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL) + ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1) + ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2) + ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go new file mode 100644 index 00000000..79a38a0b --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go @@ -0,0 +1,71 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +// HWCAP/HWCAP2 bits. These are exposed by Linux. +const ( + hwcap_FP = 1 << 0 + hwcap_ASIMD = 1 << 1 + hwcap_EVTSTRM = 1 << 2 + hwcap_AES = 1 << 3 + hwcap_PMULL = 1 << 4 + hwcap_SHA1 = 1 << 5 + hwcap_SHA2 = 1 << 6 + hwcap_CRC32 = 1 << 7 + hwcap_ATOMICS = 1 << 8 + hwcap_FPHP = 1 << 9 + hwcap_ASIMDHP = 1 << 10 + hwcap_CPUID = 1 << 11 + hwcap_ASIMDRDM = 1 << 12 + hwcap_JSCVT = 1 << 13 + hwcap_FCMA = 1 << 14 + hwcap_LRCPC = 1 << 15 + hwcap_DCPOP = 1 << 16 + hwcap_SHA3 = 1 << 17 + hwcap_SM3 = 1 << 18 + hwcap_SM4 = 1 << 19 + hwcap_ASIMDDP = 1 << 20 + hwcap_SHA512 = 1 << 21 + hwcap_SVE = 1 << 22 + hwcap_ASIMDFHM = 1 << 23 +) + +func doinit() { + if err := readHWCAP(); err != nil { + // failed to read /proc/self/auxv, try reading registers directly + readARM64Registers() + return + } + + // HWCAP feature bits + ARM64.HasFP = isSet(hwCap, hwcap_FP) + ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) + ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) + ARM64.HasAES = isSet(hwCap, hwcap_AES) + ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) + ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) + ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) + ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) + ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) + ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) + ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) + ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) + ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) + ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) + ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) + ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) + ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) + ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) + ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) + ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) + ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) + ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) + ARM64.HasSVE = isSet(hwCap, hwcap_SVE) + ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go new file mode 100644 index 00000000..6000db4c --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go @@ -0,0 +1,24 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && (mips64 || mips64le) +// +build linux +// +build mips64 mips64le + +package cpu + +// HWCAP bits. These are exposed by the Linux kernel 5.4. +const ( + // CPU features + hwcap_MIPS_MSA = 1 << 1 +) + +func doinit() { + // HWCAP feature bits + MIPS64X.HasMSA = isSet(hwCap, hwcap_MIPS_MSA) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go new file mode 100644 index 00000000..f4992b1a --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -0,0 +1,10 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x +// +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x + +package cpu + +func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go new file mode 100644 index 00000000..021356d6 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go @@ -0,0 +1,32 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && (ppc64 || ppc64le) +// +build linux +// +build ppc64 ppc64le + +package cpu + +// HWCAP/HWCAP2 bits. These are exposed by the kernel. +const ( + // ISA Level + _PPC_FEATURE2_ARCH_2_07 = 0x80000000 + _PPC_FEATURE2_ARCH_3_00 = 0x00800000 + + // CPU features + _PPC_FEATURE2_DARN = 0x00200000 + _PPC_FEATURE2_SCV = 0x00100000 +) + +func doinit() { + // HWCAP2 feature bits + PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) + PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) + PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) + PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go new file mode 100644 index 00000000..1517ac61 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go @@ -0,0 +1,40 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const ( + // bit mask values from /usr/include/bits/hwcap.h + hwcap_ZARCH = 2 + hwcap_STFLE = 4 + hwcap_MSA = 8 + hwcap_LDISP = 16 + hwcap_EIMM = 32 + hwcap_DFP = 64 + hwcap_ETF3EH = 256 + hwcap_VX = 2048 + hwcap_VXE = 8192 +) + +func initS390Xbase() { + // test HWCAP bit vector + has := func(featureMask uint) bool { + return hwCap&featureMask == featureMask + } + + // mandatory + S390X.HasZARCH = has(hwcap_ZARCH) + + // optional + S390X.HasSTFLE = has(hwcap_STFLE) + S390X.HasLDISP = has(hwcap_LDISP) + S390X.HasEIMM = has(hwcap_EIMM) + S390X.HasETF3EH = has(hwcap_ETF3EH) + S390X.HasDFP = has(hwcap_DFP) + S390X.HasMSA = has(hwcap_MSA) + S390X.HasVX = has(hwcap_VX) + if S390X.HasVX { + S390X.HasVXE = has(hwcap_VXE) + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_loong64.go new file mode 100644 index 00000000..0f57b05b --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_loong64.go @@ -0,0 +1,13 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build loong64 +// +build loong64 + +package cpu + +const cacheLineSize = 64 + +func initOptions() { +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go new file mode 100644 index 00000000..f4063c66 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build mips64 || mips64le +// +build mips64 mips64le + +package cpu + +const cacheLineSize = 32 + +func initOptions() { + options = []option{ + {Name: "msa", Feature: &MIPS64X.HasMSA}, + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go new file mode 100644 index 00000000..07c4e36d --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go @@ -0,0 +1,12 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build mips || mipsle +// +build mips mipsle + +package cpu + +const cacheLineSize = 32 + +func initOptions() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go new file mode 100644 index 00000000..ebfb3fc8 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go @@ -0,0 +1,173 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "syscall" + "unsafe" +) + +// Minimal copy of functionality from x/sys/unix so the cpu package can call +// sysctl without depending on x/sys/unix. + +const ( + _CTL_QUERY = -2 + + _SYSCTL_VERS_1 = 0x1000000 +) + +var _zero uintptr + +func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, errno := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(_p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen)) + if errno != 0 { + return errno + } + return nil +} + +type sysctlNode struct { + Flags uint32 + Num int32 + Name [32]int8 + Ver uint32 + __rsvd uint32 + Un [16]byte + _sysctl_size [8]byte + _sysctl_func [8]byte + _sysctl_parent [8]byte + _sysctl_desc [8]byte +} + +func sysctlNodes(mib []int32) ([]sysctlNode, error) { + var olen uintptr + + // Get a list of all sysctl nodes below the given MIB by performing + // a sysctl for the given MIB with CTL_QUERY appended. + mib = append(mib, _CTL_QUERY) + qnode := sysctlNode{Flags: _SYSCTL_VERS_1} + qp := (*byte)(unsafe.Pointer(&qnode)) + sz := unsafe.Sizeof(qnode) + if err := sysctl(mib, nil, &olen, qp, sz); err != nil { + return nil, err + } + + // Now that we know the size, get the actual nodes. + nodes := make([]sysctlNode, olen/sz) + np := (*byte)(unsafe.Pointer(&nodes[0])) + if err := sysctl(mib, np, &olen, qp, sz); err != nil { + return nil, err + } + + return nodes, nil +} + +func nametomib(name string) ([]int32, error) { + // Split name into components. + var parts []string + last := 0 + for i := 0; i < len(name); i++ { + if name[i] == '.' { + parts = append(parts, name[last:i]) + last = i + 1 + } + } + parts = append(parts, name[last:]) + + mib := []int32{} + // Discover the nodes and construct the MIB OID. + for partno, part := range parts { + nodes, err := sysctlNodes(mib) + if err != nil { + return nil, err + } + for _, node := range nodes { + n := make([]byte, 0) + for i := range node.Name { + if node.Name[i] != 0 { + n = append(n, byte(node.Name[i])) + } + } + if string(n) == part { + mib = append(mib, int32(node.Num)) + break + } + } + if len(mib) != partno+1 { + return nil, err + } + } + + return mib, nil +} + +// aarch64SysctlCPUID is struct aarch64_sysctl_cpu_id from NetBSD's +type aarch64SysctlCPUID struct { + midr uint64 /* Main ID Register */ + revidr uint64 /* Revision ID Register */ + mpidr uint64 /* Multiprocessor Affinity Register */ + aa64dfr0 uint64 /* A64 Debug Feature Register 0 */ + aa64dfr1 uint64 /* A64 Debug Feature Register 1 */ + aa64isar0 uint64 /* A64 Instruction Set Attribute Register 0 */ + aa64isar1 uint64 /* A64 Instruction Set Attribute Register 1 */ + aa64mmfr0 uint64 /* A64 Memory Model Feature Register 0 */ + aa64mmfr1 uint64 /* A64 Memory Model Feature Register 1 */ + aa64mmfr2 uint64 /* A64 Memory Model Feature Register 2 */ + aa64pfr0 uint64 /* A64 Processor Feature Register 0 */ + aa64pfr1 uint64 /* A64 Processor Feature Register 1 */ + aa64zfr0 uint64 /* A64 SVE Feature ID Register 0 */ + mvfr0 uint32 /* Media and VFP Feature Register 0 */ + mvfr1 uint32 /* Media and VFP Feature Register 1 */ + mvfr2 uint32 /* Media and VFP Feature Register 2 */ + pad uint32 + clidr uint64 /* Cache Level ID Register */ + ctr uint64 /* Cache Type Register */ +} + +func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) { + mib, err := nametomib(name) + if err != nil { + return nil, err + } + + out := aarch64SysctlCPUID{} + n := unsafe.Sizeof(out) + _, _, errno := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(len(mib)), + uintptr(unsafe.Pointer(&out)), + uintptr(unsafe.Pointer(&n)), + uintptr(0), + uintptr(0)) + if errno != 0 { + return nil, errno + } + return &out, nil +} + +func doinit() { + cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id") + if err != nil { + setMinimalFeatures() + return + } + parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0) + + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm.go new file mode 100644 index 00000000..d7b4fb4c --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_arm.go @@ -0,0 +1,10 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux && arm +// +build !linux,arm + +package cpu + +func archInit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go new file mode 100644 index 00000000..f8c484f5 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go @@ -0,0 +1,10 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux && !netbsd && arm64 +// +build !linux,!netbsd,arm64 + +package cpu + +func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go new file mode 100644 index 00000000..0dafe964 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go @@ -0,0 +1,13 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux && (mips64 || mips64le) +// +build !linux +// +build mips64 mips64le + +package cpu + +func archInit() { + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go new file mode 100644 index 00000000..4e8acd16 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go @@ -0,0 +1,17 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64 || ppc64le +// +build ppc64 ppc64le + +package cpu + +const cacheLineSize = 128 + +func initOptions() { + options = []option{ + {Name: "darn", Feature: &PPC64.HasDARN}, + {Name: "scv", Feature: &PPC64.HasSCV}, + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go new file mode 100644 index 00000000..bd6c128a --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go @@ -0,0 +1,12 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build riscv64 +// +build riscv64 + +package cpu + +const cacheLineSize = 32 + +func initOptions() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_s390x.go new file mode 100644 index 00000000..5881b883 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.go @@ -0,0 +1,172 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 256 + +func initOptions() { + options = []option{ + {Name: "zarch", Feature: &S390X.HasZARCH, Required: true}, + {Name: "stfle", Feature: &S390X.HasSTFLE, Required: true}, + {Name: "ldisp", Feature: &S390X.HasLDISP, Required: true}, + {Name: "eimm", Feature: &S390X.HasEIMM, Required: true}, + {Name: "dfp", Feature: &S390X.HasDFP}, + {Name: "etf3eh", Feature: &S390X.HasETF3EH}, + {Name: "msa", Feature: &S390X.HasMSA}, + {Name: "aes", Feature: &S390X.HasAES}, + {Name: "aescbc", Feature: &S390X.HasAESCBC}, + {Name: "aesctr", Feature: &S390X.HasAESCTR}, + {Name: "aesgcm", Feature: &S390X.HasAESGCM}, + {Name: "ghash", Feature: &S390X.HasGHASH}, + {Name: "sha1", Feature: &S390X.HasSHA1}, + {Name: "sha256", Feature: &S390X.HasSHA256}, + {Name: "sha3", Feature: &S390X.HasSHA3}, + {Name: "sha512", Feature: &S390X.HasSHA512}, + {Name: "vx", Feature: &S390X.HasVX}, + {Name: "vxe", Feature: &S390X.HasVXE}, + } +} + +// bitIsSet reports whether the bit at index is set. The bit index +// is in big endian order, so bit index 0 is the leftmost bit. +func bitIsSet(bits []uint64, index uint) bool { + return bits[index/64]&((1<<63)>>(index%64)) != 0 +} + +// facility is a bit index for the named facility. +type facility uint8 + +const ( + // mandatory facilities + zarch facility = 1 // z architecture mode is active + stflef facility = 7 // store-facility-list-extended + ldisp facility = 18 // long-displacement + eimm facility = 21 // extended-immediate + + // miscellaneous facilities + dfp facility = 42 // decimal-floating-point + etf3eh facility = 30 // extended-translation 3 enhancement + + // cryptography facilities + msa facility = 17 // message-security-assist + msa3 facility = 76 // message-security-assist extension 3 + msa4 facility = 77 // message-security-assist extension 4 + msa5 facility = 57 // message-security-assist extension 5 + msa8 facility = 146 // message-security-assist extension 8 + msa9 facility = 155 // message-security-assist extension 9 + + // vector facilities + vx facility = 129 // vector facility + vxe facility = 135 // vector-enhancements 1 + vxe2 facility = 148 // vector-enhancements 2 +) + +// facilityList contains the result of an STFLE call. +// Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type facilityList struct { + bits [4]uint64 +} + +// Has reports whether the given facilities are present. +func (s *facilityList) Has(fs ...facility) bool { + if len(fs) == 0 { + panic("no facility bits provided") + } + for _, f := range fs { + if !bitIsSet(s.bits[:], uint(f)) { + return false + } + } + return true +} + +// function is the code for the named cryptographic function. +type function uint8 + +const ( + // KM{,A,C,CTR} function codes + aes128 function = 18 // AES-128 + aes192 function = 19 // AES-192 + aes256 function = 20 // AES-256 + + // K{I,L}MD function codes + sha1 function = 1 // SHA-1 + sha256 function = 2 // SHA-256 + sha512 function = 3 // SHA-512 + sha3_224 function = 32 // SHA3-224 + sha3_256 function = 33 // SHA3-256 + sha3_384 function = 34 // SHA3-384 + sha3_512 function = 35 // SHA3-512 + shake128 function = 36 // SHAKE-128 + shake256 function = 37 // SHAKE-256 + + // KLMD function codes + ghash function = 65 // GHASH +) + +// queryResult contains the result of a Query function +// call. Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type queryResult struct { + bits [2]uint64 +} + +// Has reports whether the given functions are present. +func (q *queryResult) Has(fns ...function) bool { + if len(fns) == 0 { + panic("no function codes provided") + } + for _, f := range fns { + if !bitIsSet(q.bits[:], uint(f)) { + return false + } + } + return true +} + +func doinit() { + initS390Xbase() + + // We need implementations of stfle, km and so on + // to detect cryptographic features. + if !haveAsmFunctions() { + return + } + + // optional cryptographic functions + if S390X.HasMSA { + aes := []function{aes128, aes192, aes256} + + // cipher message + km, kmc := kmQuery(), kmcQuery() + S390X.HasAES = km.Has(aes...) + S390X.HasAESCBC = kmc.Has(aes...) + if S390X.HasSTFLE { + facilities := stfle() + if facilities.Has(msa4) { + kmctr := kmctrQuery() + S390X.HasAESCTR = kmctr.Has(aes...) + } + if facilities.Has(msa8) { + kma := kmaQuery() + S390X.HasAESGCM = kma.Has(aes...) + } + } + + // compute message digest + kimd := kimdQuery() // intermediate (no padding) + klmd := klmdQuery() // last (padding) + S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) + S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) + S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) + S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist + sha3 := []function{ + sha3_224, sha3_256, sha3_384, sha3_512, + shake128, shake256, + } + S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/vendor/golang.org/x/sys/cpu/cpu_s390x.s new file mode 100644 index 00000000..96f81e20 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.s @@ -0,0 +1,58 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc +// +build gc + +#include "textflag.h" + +// func stfle() facilityList +TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 + MOVD $ret+0(FP), R1 + MOVD $3, R0 // last doubleword index to store + XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) + WORD $0xb2b01000 // store facility list extended (STFLE) + RET + +// func kmQuery() queryResult +TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KM-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB92E0024 // cipher message (KM) + RET + +// func kmcQuery() queryResult +TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KMC-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB92F0024 // cipher message with chaining (KMC) + RET + +// func kmctrQuery() queryResult +TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KMCTR-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB92D4024 // cipher message with counter (KMCTR) + RET + +// func kmaQuery() queryResult +TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KMA-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xb9296024 // cipher message with authentication (KMA) + RET + +// func kimdQuery() queryResult +TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KIMD-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB93E0024 // compute intermediate message digest (KIMD) + RET + +// func klmdQuery() queryResult +TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KLMD-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB93F0024 // compute last message digest (KLMD) + RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_wasm.go b/vendor/golang.org/x/sys/cpu/cpu_wasm.go new file mode 100644 index 00000000..7747d888 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_wasm.go @@ -0,0 +1,18 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build wasm +// +build wasm + +package cpu + +// We're compiling the cpu package for an unknown (software-abstracted) CPU. +// Make CacheLinePad an empty struct and hope that the usual struct alignment +// rules are good enough. + +const cacheLineSize = 0 + +func initOptions() {} + +func archInit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go new file mode 100644 index 00000000..f5aacfc8 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -0,0 +1,145 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 || amd64 || amd64p32 +// +build 386 amd64 amd64p32 + +package cpu + +import "runtime" + +const cacheLineSize = 64 + +func initOptions() { + options = []option{ + {Name: "adx", Feature: &X86.HasADX}, + {Name: "aes", Feature: &X86.HasAES}, + {Name: "avx", Feature: &X86.HasAVX}, + {Name: "avx2", Feature: &X86.HasAVX2}, + {Name: "avx512", Feature: &X86.HasAVX512}, + {Name: "avx512f", Feature: &X86.HasAVX512F}, + {Name: "avx512cd", Feature: &X86.HasAVX512CD}, + {Name: "avx512er", Feature: &X86.HasAVX512ER}, + {Name: "avx512pf", Feature: &X86.HasAVX512PF}, + {Name: "avx512vl", Feature: &X86.HasAVX512VL}, + {Name: "avx512bw", Feature: &X86.HasAVX512BW}, + {Name: "avx512dq", Feature: &X86.HasAVX512DQ}, + {Name: "avx512ifma", Feature: &X86.HasAVX512IFMA}, + {Name: "avx512vbmi", Feature: &X86.HasAVX512VBMI}, + {Name: "avx512vnniw", Feature: &X86.HasAVX5124VNNIW}, + {Name: "avx5124fmaps", Feature: &X86.HasAVX5124FMAPS}, + {Name: "avx512vpopcntdq", Feature: &X86.HasAVX512VPOPCNTDQ}, + {Name: "avx512vpclmulqdq", Feature: &X86.HasAVX512VPCLMULQDQ}, + {Name: "avx512vnni", Feature: &X86.HasAVX512VNNI}, + {Name: "avx512gfni", Feature: &X86.HasAVX512GFNI}, + {Name: "avx512vaes", Feature: &X86.HasAVX512VAES}, + {Name: "avx512vbmi2", Feature: &X86.HasAVX512VBMI2}, + {Name: "avx512bitalg", Feature: &X86.HasAVX512BITALG}, + {Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, + {Name: "bmi1", Feature: &X86.HasBMI1}, + {Name: "bmi2", Feature: &X86.HasBMI2}, + {Name: "cx16", Feature: &X86.HasCX16}, + {Name: "erms", Feature: &X86.HasERMS}, + {Name: "fma", Feature: &X86.HasFMA}, + {Name: "osxsave", Feature: &X86.HasOSXSAVE}, + {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ}, + {Name: "popcnt", Feature: &X86.HasPOPCNT}, + {Name: "rdrand", Feature: &X86.HasRDRAND}, + {Name: "rdseed", Feature: &X86.HasRDSEED}, + {Name: "sse3", Feature: &X86.HasSSE3}, + {Name: "sse41", Feature: &X86.HasSSE41}, + {Name: "sse42", Feature: &X86.HasSSE42}, + {Name: "ssse3", Feature: &X86.HasSSSE3}, + + // These capabilities should always be enabled on amd64: + {Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"}, + } +} + +func archInit() { + + Initialized = true + + maxID, _, _, _ := cpuid(0, 0) + + if maxID < 1 { + return + } + + _, _, ecx1, edx1 := cpuid(1, 0) + X86.HasSSE2 = isSet(26, edx1) + + X86.HasSSE3 = isSet(0, ecx1) + X86.HasPCLMULQDQ = isSet(1, ecx1) + X86.HasSSSE3 = isSet(9, ecx1) + X86.HasFMA = isSet(12, ecx1) + X86.HasCX16 = isSet(13, ecx1) + X86.HasSSE41 = isSet(19, ecx1) + X86.HasSSE42 = isSet(20, ecx1) + X86.HasPOPCNT = isSet(23, ecx1) + X86.HasAES = isSet(25, ecx1) + X86.HasOSXSAVE = isSet(27, ecx1) + X86.HasRDRAND = isSet(30, ecx1) + + var osSupportsAVX, osSupportsAVX512 bool + // For XGETBV, OSXSAVE bit is required and sufficient. + if X86.HasOSXSAVE { + eax, _ := xgetbv() + // Check if XMM and YMM registers have OS support. + osSupportsAVX = isSet(1, eax) && isSet(2, eax) + + if runtime.GOOS == "darwin" { + // Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers. + // Since users can't rely on mask register contents, let's not advertise AVX-512 support. + // See issue 49233. + osSupportsAVX512 = false + } else { + // Check if OPMASK and ZMM registers have OS support. + osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) + } + } + + X86.HasAVX = isSet(28, ecx1) && osSupportsAVX + + if maxID < 7 { + return + } + + _, ebx7, ecx7, edx7 := cpuid(7, 0) + X86.HasBMI1 = isSet(3, ebx7) + X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX + X86.HasBMI2 = isSet(8, ebx7) + X86.HasERMS = isSet(9, ebx7) + X86.HasRDSEED = isSet(18, ebx7) + X86.HasADX = isSet(19, ebx7) + + X86.HasAVX512 = isSet(16, ebx7) && osSupportsAVX512 // Because avx-512 foundation is the core required extension + if X86.HasAVX512 { + X86.HasAVX512F = true + X86.HasAVX512CD = isSet(28, ebx7) + X86.HasAVX512ER = isSet(27, ebx7) + X86.HasAVX512PF = isSet(26, ebx7) + X86.HasAVX512VL = isSet(31, ebx7) + X86.HasAVX512BW = isSet(30, ebx7) + X86.HasAVX512DQ = isSet(17, ebx7) + X86.HasAVX512IFMA = isSet(21, ebx7) + X86.HasAVX512VBMI = isSet(1, ecx7) + X86.HasAVX5124VNNIW = isSet(2, edx7) + X86.HasAVX5124FMAPS = isSet(3, edx7) + X86.HasAVX512VPOPCNTDQ = isSet(14, ecx7) + X86.HasAVX512VPCLMULQDQ = isSet(10, ecx7) + X86.HasAVX512VNNI = isSet(11, ecx7) + X86.HasAVX512GFNI = isSet(8, ecx7) + X86.HasAVX512VAES = isSet(9, ecx7) + X86.HasAVX512VBMI2 = isSet(6, ecx7) + X86.HasAVX512BITALG = isSet(12, ecx7) + + eax71, _, _, _ := cpuid(7, 1) + X86.HasAVX512BF16 = isSet(5, eax71) + } +} + +func isSet(bitpos uint, value uint32) bool { + return value&(1<> 63)) +) + +// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 +// These are initialized in cpu_$GOARCH.go +// and should not be changed after they are initialized. +var hwCap uint +var hwCap2 uint + +func readHWCAP() error { + buf, err := ioutil.ReadFile(procAuxv) + if err != nil { + // e.g. on android /proc/self/auxv is not accessible, so silently + // ignore the error and leave Initialized = false. On some + // architectures (e.g. arm64) doinit() implements a fallback + // readout and will set Initialized = true again. + return err + } + bo := hostByteOrder() + for len(buf) >= 2*(uintSize/8) { + var tag, val uint + switch uintSize { + case 32: + tag = uint(bo.Uint32(buf[0:])) + val = uint(bo.Uint32(buf[4:])) + buf = buf[8:] + case 64: + tag = uint(bo.Uint64(buf[0:])) + val = uint(bo.Uint64(buf[8:])) + buf = buf[16:] + } + switch tag { + case _AT_HWCAP: + hwCap = val + case _AT_HWCAP2: + hwCap2 = val + } + } + return nil +} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go b/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go new file mode 100644 index 00000000..96134157 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Recreate a getsystemcfg syscall handler instead of +// using the one provided by x/sys/unix to avoid having +// the dependency between them. (See golang.org/issue/32102) +// Moreover, this file will be used during the building of +// gccgo's libgo and thus must not used a CGo method. + +//go:build aix && gccgo +// +build aix,gccgo + +package cpu + +import ( + "syscall" +) + +//extern getsystemcfg +func gccgoGetsystemcfg(label uint32) (r uint64) + +func callgetsystemcfg(label int) (r1 uintptr, e1 syscall.Errno) { + r1 = uintptr(gccgoGetsystemcfg(uint32(label))) + e1 = syscall.GetErrno() + return +} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go new file mode 100644 index 00000000..904be42f --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go @@ -0,0 +1,36 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Minimal copy of x/sys/unix so the cpu package can make a +// system call on AIX without depending on x/sys/unix. +// (See golang.org/issue/32102) + +//go:build aix && ppc64 && gc +// +build aix,ppc64,gc + +package cpu + +import ( + "syscall" + "unsafe" +) + +//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o" + +//go:linkname libc_getsystemcfg libc_getsystemcfg + +type syscallFunc uintptr + +var libc_getsystemcfg syscallFunc + +type errno = syscall.Errno + +// Implemented in runtime/syscall_aix.go. +func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) +func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) + +func callgetsystemcfg(label int) (r1 uintptr, e1 errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0) + return +} diff --git a/vendor/kubevirt.io/api/LICENSE b/vendor/kubevirt.io/api/LICENSE new file mode 100644 index 00000000..549d874d --- /dev/null +++ b/vendor/kubevirt.io/api/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 The KubeVirt Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/kubevirt.io/api/core/register.go b/vendor/kubevirt.io/api/core/register.go new file mode 100644 index 00000000..22080c71 --- /dev/null +++ b/vendor/kubevirt.io/api/core/register.go @@ -0,0 +1,4 @@ +package core + +// GroupName is the group name use in this package +const GroupName = "kubevirt.io" diff --git a/vendor/kubevirt.io/api/core/v1/componentconfig.go b/vendor/kubevirt.io/api/core/v1/componentconfig.go new file mode 100644 index 00000000..4d26dbd2 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/componentconfig.go @@ -0,0 +1,48 @@ +package v1 + +// This code is copied from +// https://github.com/kubevirt/controller-lifecycle-operator-sdk/blob/master/pkg/sdk/api/types.go +// in order to avoid dependency loops + +import ( + corev1 "k8s.io/api/core/v1" +) + +// NodePlacement describes node scheduling configuration. +type NodePlacement struct { + // nodeSelector is the node selector applied to the relevant kind of pods + // It specifies a map of key-value pairs: for the pod to be eligible to run on a node, + // the node must have each of the indicated key-value pairs as labels + // (it can have additional labels as well). + // See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + // +kubebuilder:validation:Optional + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // affinity enables pod affinity/anti-affinity placement expanding the types of constraints + // that can be expressed with nodeSelector. + // affinity is going to be applied to the relevant kind of pods in parallel with nodeSelector + // See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + // +kubebuilder:validation:Optional + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + + // tolerations is a list of tolerations applied to the relevant kind of pods + // See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info. + // These are additional tolerations other than default ones. + // +kubebuilder:validation:Optional + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` +} + +type ComponentConfig struct { + // nodePlacement describes scheduling configuration for specific + // KubeVirt components + //+optional + NodePlacement *NodePlacement `json:"nodePlacement,omitempty"` + // replicas indicates how many replicas should be created for each KubeVirt infrastructure + // component (like virt-api or virt-controller). Defaults to 2. + // WARNING: this is an advanced feature that prevents auto-scaling for core kubevirt components. Please use with caution! + //+optional + Replicas *uint8 `json:"replicas,omitempty"` +} diff --git a/vendor/kubevirt.io/api/core/v1/deepcopy_generated.go b/vendor/kubevirt.io/api/core/v1/deepcopy_generated.go new file mode 100644 index 00000000..03446ec9 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/deepcopy_generated.go @@ -0,0 +1,5087 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2022 The KubeVirt Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + types "k8s.io/apimachinery/pkg/types" + + v1beta1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AccessCredential) DeepCopyInto(out *AccessCredential) { + *out = *in + if in.SSHPublicKey != nil { + in, out := &in.SSHPublicKey, &out.SSHPublicKey + *out = new(SSHPublicKeyAccessCredential) + (*in).DeepCopyInto(*out) + } + if in.UserPassword != nil { + in, out := &in.UserPassword, &out.UserPassword + *out = new(UserPasswordAccessCredential) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessCredential. +func (in *AccessCredential) DeepCopy() *AccessCredential { + if in == nil { + return nil + } + out := new(AccessCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AccessCredentialSecretSource) DeepCopyInto(out *AccessCredentialSecretSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessCredentialSecretSource. +func (in *AccessCredentialSecretSource) DeepCopy() *AccessCredentialSecretSource { + if in == nil { + return nil + } + out := new(AccessCredentialSecretSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddVolumeOptions) DeepCopyInto(out *AddVolumeOptions) { + *out = *in + if in.Disk != nil { + in, out := &in.Disk, &out.Disk + *out = new(Disk) + (*in).DeepCopyInto(*out) + } + if in.VolumeSource != nil { + in, out := &in.VolumeSource, &out.VolumeSource + *out = new(HotplugVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddVolumeOptions. +func (in *AddVolumeOptions) DeepCopy() *AddVolumeOptions { + if in == nil { + return nil + } + out := new(AddVolumeOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizedKeysFile) DeepCopyInto(out *AuthorizedKeysFile) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizedKeysFile. +func (in *AuthorizedKeysFile) DeepCopy() *AuthorizedKeysFile { + if in == nil { + return nil + } + out := new(AuthorizedKeysFile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BIOS) DeepCopyInto(out *BIOS) { + *out = *in + if in.UseSerial != nil { + in, out := &in.UseSerial, &out.UseSerial + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BIOS. +func (in *BIOS) DeepCopy() *BIOS { + if in == nil { + return nil + } + out := new(BIOS) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BlockSize) DeepCopyInto(out *BlockSize) { + *out = *in + if in.Custom != nil { + in, out := &in.Custom, &out.Custom + *out = new(CustomBlockSize) + **out = **in + } + if in.MatchVolume != nil { + in, out := &in.MatchVolume, &out.MatchVolume + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockSize. +func (in *BlockSize) DeepCopy() *BlockSize { + if in == nil { + return nil + } + out := new(BlockSize) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Bootloader) DeepCopyInto(out *Bootloader) { + *out = *in + if in.BIOS != nil { + in, out := &in.BIOS, &out.BIOS + *out = new(BIOS) + (*in).DeepCopyInto(*out) + } + if in.EFI != nil { + in, out := &in.EFI, &out.EFI + *out = new(EFI) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Bootloader. +func (in *Bootloader) DeepCopy() *Bootloader { + if in == nil { + return nil + } + out := new(Bootloader) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDRomTarget) DeepCopyInto(out *CDRomTarget) { + *out = *in + if in.ReadOnly != nil { + in, out := &in.ReadOnly, &out.ReadOnly + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDRomTarget. +func (in *CDRomTarget) DeepCopy() *CDRomTarget { + if in == nil { + return nil + } + out := new(CDRomTarget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPU) DeepCopyInto(out *CPU) { + *out = *in + if in.Features != nil { + in, out := &in.Features, &out.Features + *out = make([]CPUFeature, len(*in)) + copy(*out, *in) + } + if in.NUMA != nil { + in, out := &in.NUMA, &out.NUMA + *out = new(NUMA) + (*in).DeepCopyInto(*out) + } + if in.Realtime != nil { + in, out := &in.Realtime, &out.Realtime + *out = new(Realtime) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPU. +func (in *CPU) DeepCopy() *CPU { + if in == nil { + return nil + } + out := new(CPU) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPUFeature) DeepCopyInto(out *CPUFeature) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPUFeature. +func (in *CPUFeature) DeepCopy() *CPUFeature { + if in == nil { + return nil + } + out := new(CPUFeature) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertConfig) DeepCopyInto(out *CertConfig) { + *out = *in + if in.Duration != nil { + in, out := &in.Duration, &out.Duration + *out = new(metav1.Duration) + **out = **in + } + if in.RenewBefore != nil { + in, out := &in.RenewBefore, &out.RenewBefore + *out = new(metav1.Duration) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertConfig. +func (in *CertConfig) DeepCopy() *CertConfig { + if in == nil { + return nil + } + out := new(CertConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Chassis) DeepCopyInto(out *Chassis) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Chassis. +func (in *Chassis) DeepCopy() *Chassis { + if in == nil { + return nil + } + out := new(Chassis) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientPassthroughDevices) DeepCopyInto(out *ClientPassthroughDevices) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientPassthroughDevices. +func (in *ClientPassthroughDevices) DeepCopy() *ClientPassthroughDevices { + if in == nil { + return nil + } + out := new(ClientPassthroughDevices) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Clock) DeepCopyInto(out *Clock) { + *out = *in + in.ClockOffset.DeepCopyInto(&out.ClockOffset) + if in.Timer != nil { + in, out := &in.Timer, &out.Timer + *out = new(Timer) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Clock. +func (in *Clock) DeepCopy() *Clock { + if in == nil { + return nil + } + out := new(Clock) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClockOffset) DeepCopyInto(out *ClockOffset) { + *out = *in + if in.UTC != nil { + in, out := &in.UTC, &out.UTC + *out = new(ClockOffsetUTC) + (*in).DeepCopyInto(*out) + } + if in.Timezone != nil { + in, out := &in.Timezone, &out.Timezone + *out = new(ClockOffsetTimezone) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClockOffset. +func (in *ClockOffset) DeepCopy() *ClockOffset { + if in == nil { + return nil + } + out := new(ClockOffset) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClockOffsetUTC) DeepCopyInto(out *ClockOffsetUTC) { + *out = *in + if in.OffsetSeconds != nil { + in, out := &in.OffsetSeconds, &out.OffsetSeconds + *out = new(int) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClockOffsetUTC. +func (in *ClockOffsetUTC) DeepCopy() *ClockOffsetUTC { + if in == nil { + return nil + } + out := new(ClockOffsetUTC) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudInitConfigDriveSource) DeepCopyInto(out *CloudInitConfigDriveSource) { + *out = *in + if in.UserDataSecretRef != nil { + in, out := &in.UserDataSecretRef, &out.UserDataSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.NetworkDataSecretRef != nil { + in, out := &in.NetworkDataSecretRef, &out.NetworkDataSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudInitConfigDriveSource. +func (in *CloudInitConfigDriveSource) DeepCopy() *CloudInitConfigDriveSource { + if in == nil { + return nil + } + out := new(CloudInitConfigDriveSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudInitNoCloudSource) DeepCopyInto(out *CloudInitNoCloudSource) { + *out = *in + if in.UserDataSecretRef != nil { + in, out := &in.UserDataSecretRef, &out.UserDataSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.NetworkDataSecretRef != nil { + in, out := &in.NetworkDataSecretRef, &out.NetworkDataSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudInitNoCloudSource. +func (in *CloudInitNoCloudSource) DeepCopy() *CloudInitNoCloudSource { + if in == nil { + return nil + } + out := new(CloudInitNoCloudSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterProfilerRequest) DeepCopyInto(out *ClusterProfilerRequest) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProfilerRequest. +func (in *ClusterProfilerRequest) DeepCopy() *ClusterProfilerRequest { + if in == nil { + return nil + } + out := new(ClusterProfilerRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterProfilerResults) DeepCopyInto(out *ClusterProfilerResults) { + *out = *in + if in.ComponentResults != nil { + in, out := &in.ComponentResults, &out.ComponentResults + *out = make(map[string]ProfilerResult, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProfilerResults. +func (in *ClusterProfilerResults) DeepCopy() *ClusterProfilerResults { + if in == nil { + return nil + } + out := new(ClusterProfilerResults) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentConfig) DeepCopyInto(out *ComponentConfig) { + *out = *in + if in.NodePlacement != nil { + in, out := &in.NodePlacement, &out.NodePlacement + *out = new(NodePlacement) + (*in).DeepCopyInto(*out) + } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(byte) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentConfig. +func (in *ComponentConfig) DeepCopy() *ComponentConfig { + if in == nil { + return nil + } + out := new(ComponentConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigDriveSSHPublicKeyAccessCredentialPropagation) DeepCopyInto(out *ConfigDriveSSHPublicKeyAccessCredentialPropagation) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigDriveSSHPublicKeyAccessCredentialPropagation. +func (in *ConfigDriveSSHPublicKeyAccessCredentialPropagation) DeepCopy() *ConfigDriveSSHPublicKeyAccessCredentialPropagation { + if in == nil { + return nil + } + out := new(ConfigDriveSSHPublicKeyAccessCredentialPropagation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapVolumeSource) DeepCopyInto(out *ConfigMapVolumeSource) { + *out = *in + out.LocalObjectReference = in.LocalObjectReference + if in.Optional != nil { + in, out := &in.Optional, &out.Optional + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapVolumeSource. +func (in *ConfigMapVolumeSource) DeepCopy() *ConfigMapVolumeSource { + if in == nil { + return nil + } + out := new(ConfigMapVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContainerDiskSource) DeepCopyInto(out *ContainerDiskSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerDiskSource. +func (in *ContainerDiskSource) DeepCopy() *ContainerDiskSource { + if in == nil { + return nil + } + out := new(ContainerDiskSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomBlockSize) DeepCopyInto(out *CustomBlockSize) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomBlockSize. +func (in *CustomBlockSize) DeepCopy() *CustomBlockSize { + if in == nil { + return nil + } + out := new(CustomBlockSize) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomizeComponents) DeepCopyInto(out *CustomizeComponents) { + *out = *in + if in.Patches != nil { + in, out := &in.Patches, &out.Patches + *out = make([]CustomizeComponentsPatch, len(*in)) + copy(*out, *in) + } + if in.Flags != nil { + in, out := &in.Flags, &out.Flags + *out = new(Flags) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomizeComponents. +func (in *CustomizeComponents) DeepCopy() *CustomizeComponents { + if in == nil { + return nil + } + out := new(CustomizeComponents) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomizeComponentsPatch) DeepCopyInto(out *CustomizeComponentsPatch) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomizeComponentsPatch. +func (in *CustomizeComponentsPatch) DeepCopy() *CustomizeComponentsPatch { + if in == nil { + return nil + } + out := new(CustomizeComponentsPatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DHCPOptions) DeepCopyInto(out *DHCPOptions) { + *out = *in + if in.NTPServers != nil { + in, out := &in.NTPServers, &out.NTPServers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.PrivateOptions != nil { + in, out := &in.PrivateOptions, &out.PrivateOptions + *out = make([]DHCPPrivateOptions, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DHCPOptions. +func (in *DHCPOptions) DeepCopy() *DHCPOptions { + if in == nil { + return nil + } + out := new(DHCPOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DHCPPrivateOptions) DeepCopyInto(out *DHCPPrivateOptions) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DHCPPrivateOptions. +func (in *DHCPPrivateOptions) DeepCopy() *DHCPPrivateOptions { + if in == nil { + return nil + } + out := new(DHCPPrivateOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSource) DeepCopyInto(out *DataVolumeSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSource. +func (in *DataVolumeSource) DeepCopy() *DataVolumeSource { + if in == nil { + return nil + } + out := new(DataVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeTemplateDummyStatus) DeepCopyInto(out *DataVolumeTemplateDummyStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeTemplateDummyStatus. +func (in *DataVolumeTemplateDummyStatus) DeepCopy() *DataVolumeTemplateDummyStatus { + if in == nil { + return nil + } + out := new(DataVolumeTemplateDummyStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeTemplateSpec) DeepCopyInto(out *DataVolumeTemplateSpec) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(DataVolumeTemplateDummyStatus) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeTemplateSpec. +func (in *DataVolumeTemplateSpec) DeepCopy() *DataVolumeTemplateSpec { + if in == nil { + return nil + } + out := new(DataVolumeTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeveloperConfiguration) DeepCopyInto(out *DeveloperConfiguration) { + *out = *in + if in.FeatureGates != nil { + in, out := &in.FeatureGates, &out.FeatureGates + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.NodeSelectors != nil { + in, out := &in.NodeSelectors, &out.NodeSelectors + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MinimumClusterTSCFrequency != nil { + in, out := &in.MinimumClusterTSCFrequency, &out.MinimumClusterTSCFrequency + *out = new(int64) + **out = **in + } + if in.DiskVerification != nil { + in, out := &in.DiskVerification, &out.DiskVerification + *out = new(DiskVerification) + (*in).DeepCopyInto(*out) + } + if in.LogVerbosity != nil { + in, out := &in.LogVerbosity, &out.LogVerbosity + *out = new(LogVerbosity) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeveloperConfiguration. +func (in *DeveloperConfiguration) DeepCopy() *DeveloperConfiguration { + if in == nil { + return nil + } + out := new(DeveloperConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Devices) DeepCopyInto(out *Devices) { + *out = *in + if in.UseVirtioTransitional != nil { + in, out := &in.UseVirtioTransitional, &out.UseVirtioTransitional + *out = new(bool) + **out = **in + } + if in.Disks != nil { + in, out := &in.Disks, &out.Disks + *out = make([]Disk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Watchdog != nil { + in, out := &in.Watchdog, &out.Watchdog + *out = new(Watchdog) + (*in).DeepCopyInto(*out) + } + if in.Interfaces != nil { + in, out := &in.Interfaces, &out.Interfaces + *out = make([]Interface, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Inputs != nil { + in, out := &in.Inputs, &out.Inputs + *out = make([]Input, len(*in)) + copy(*out, *in) + } + if in.AutoattachPodInterface != nil { + in, out := &in.AutoattachPodInterface, &out.AutoattachPodInterface + *out = new(bool) + **out = **in + } + if in.AutoattachGraphicsDevice != nil { + in, out := &in.AutoattachGraphicsDevice, &out.AutoattachGraphicsDevice + *out = new(bool) + **out = **in + } + if in.AutoattachSerialConsole != nil { + in, out := &in.AutoattachSerialConsole, &out.AutoattachSerialConsole + *out = new(bool) + **out = **in + } + if in.AutoattachMemBalloon != nil { + in, out := &in.AutoattachMemBalloon, &out.AutoattachMemBalloon + *out = new(bool) + **out = **in + } + if in.Rng != nil { + in, out := &in.Rng, &out.Rng + *out = new(Rng) + **out = **in + } + if in.BlockMultiQueue != nil { + in, out := &in.BlockMultiQueue, &out.BlockMultiQueue + *out = new(bool) + **out = **in + } + if in.NetworkInterfaceMultiQueue != nil { + in, out := &in.NetworkInterfaceMultiQueue, &out.NetworkInterfaceMultiQueue + *out = new(bool) + **out = **in + } + if in.GPUs != nil { + in, out := &in.GPUs, &out.GPUs + *out = make([]GPU, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Filesystems != nil { + in, out := &in.Filesystems, &out.Filesystems + *out = make([]Filesystem, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.HostDevices != nil { + in, out := &in.HostDevices, &out.HostDevices + *out = make([]HostDevice, len(*in)) + copy(*out, *in) + } + if in.ClientPassthrough != nil { + in, out := &in.ClientPassthrough, &out.ClientPassthrough + *out = new(ClientPassthroughDevices) + **out = **in + } + if in.Sound != nil { + in, out := &in.Sound, &out.Sound + *out = new(SoundDevice) + **out = **in + } + if in.TPM != nil { + in, out := &in.TPM, &out.TPM + *out = new(TPMDevice) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Devices. +func (in *Devices) DeepCopy() *Devices { + if in == nil { + return nil + } + out := new(Devices) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Disk) DeepCopyInto(out *Disk) { + *out = *in + in.DiskDevice.DeepCopyInto(&out.DiskDevice) + if in.BootOrder != nil { + in, out := &in.BootOrder, &out.BootOrder + *out = new(uint) + **out = **in + } + if in.DedicatedIOThread != nil { + in, out := &in.DedicatedIOThread, &out.DedicatedIOThread + *out = new(bool) + **out = **in + } + if in.BlockSize != nil { + in, out := &in.BlockSize, &out.BlockSize + *out = new(BlockSize) + (*in).DeepCopyInto(*out) + } + if in.Shareable != nil { + in, out := &in.Shareable, &out.Shareable + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Disk. +func (in *Disk) DeepCopy() *Disk { + if in == nil { + return nil + } + out := new(Disk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskDevice) DeepCopyInto(out *DiskDevice) { + *out = *in + if in.Disk != nil { + in, out := &in.Disk, &out.Disk + *out = new(DiskTarget) + **out = **in + } + if in.LUN != nil { + in, out := &in.LUN, &out.LUN + *out = new(LunTarget) + **out = **in + } + if in.CDRom != nil { + in, out := &in.CDRom, &out.CDRom + *out = new(CDRomTarget) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskDevice. +func (in *DiskDevice) DeepCopy() *DiskDevice { + if in == nil { + return nil + } + out := new(DiskDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskTarget) DeepCopyInto(out *DiskTarget) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskTarget. +func (in *DiskTarget) DeepCopy() *DiskTarget { + if in == nil { + return nil + } + out := new(DiskTarget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskVerification) DeepCopyInto(out *DiskVerification) { + *out = *in + if in.MemoryLimit != nil { + in, out := &in.MemoryLimit, &out.MemoryLimit + x := (*in).DeepCopy() + *out = &x + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskVerification. +func (in *DiskVerification) DeepCopy() *DiskVerification { + if in == nil { + return nil + } + out := new(DiskVerification) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DomainMemoryDumpInfo) DeepCopyInto(out *DomainMemoryDumpInfo) { + *out = *in + if in.StartTimestamp != nil { + in, out := &in.StartTimestamp, &out.StartTimestamp + *out = (*in).DeepCopy() + } + if in.EndTimestamp != nil { + in, out := &in.EndTimestamp, &out.EndTimestamp + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainMemoryDumpInfo. +func (in *DomainMemoryDumpInfo) DeepCopy() *DomainMemoryDumpInfo { + if in == nil { + return nil + } + out := new(DomainMemoryDumpInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DomainSpec) DeepCopyInto(out *DomainSpec) { + *out = *in + in.Resources.DeepCopyInto(&out.Resources) + if in.CPU != nil { + in, out := &in.CPU, &out.CPU + *out = new(CPU) + (*in).DeepCopyInto(*out) + } + if in.Memory != nil { + in, out := &in.Memory, &out.Memory + *out = new(Memory) + (*in).DeepCopyInto(*out) + } + if in.Machine != nil { + in, out := &in.Machine, &out.Machine + *out = new(Machine) + **out = **in + } + if in.Firmware != nil { + in, out := &in.Firmware, &out.Firmware + *out = new(Firmware) + (*in).DeepCopyInto(*out) + } + if in.Clock != nil { + in, out := &in.Clock, &out.Clock + *out = new(Clock) + (*in).DeepCopyInto(*out) + } + if in.Features != nil { + in, out := &in.Features, &out.Features + *out = new(Features) + (*in).DeepCopyInto(*out) + } + in.Devices.DeepCopyInto(&out.Devices) + if in.IOThreadsPolicy != nil { + in, out := &in.IOThreadsPolicy, &out.IOThreadsPolicy + *out = new(IOThreadsPolicy) + **out = **in + } + if in.Chassis != nil { + in, out := &in.Chassis, &out.Chassis + *out = new(Chassis) + **out = **in + } + if in.LaunchSecurity != nil { + in, out := &in.LaunchSecurity, &out.LaunchSecurity + *out = new(LaunchSecurity) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainSpec. +func (in *DomainSpec) DeepCopy() *DomainSpec { + if in == nil { + return nil + } + out := new(DomainSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DownwardAPIVolumeSource) DeepCopyInto(out *DownwardAPIVolumeSource) { + *out = *in + if in.Fields != nil { + in, out := &in.Fields, &out.Fields + *out = make([]corev1.DownwardAPIVolumeFile, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DownwardAPIVolumeSource. +func (in *DownwardAPIVolumeSource) DeepCopy() *DownwardAPIVolumeSource { + if in == nil { + return nil + } + out := new(DownwardAPIVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DownwardMetricsVolumeSource) DeepCopyInto(out *DownwardMetricsVolumeSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DownwardMetricsVolumeSource. +func (in *DownwardMetricsVolumeSource) DeepCopy() *DownwardMetricsVolumeSource { + if in == nil { + return nil + } + out := new(DownwardMetricsVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EFI) DeepCopyInto(out *EFI) { + *out = *in + if in.SecureBoot != nil { + in, out := &in.SecureBoot, &out.SecureBoot + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EFI. +func (in *EFI) DeepCopy() *EFI { + if in == nil { + return nil + } + out := new(EFI) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EmptyDiskSource) DeepCopyInto(out *EmptyDiskSource) { + *out = *in + out.Capacity = in.Capacity.DeepCopy() + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmptyDiskSource. +func (in *EmptyDiskSource) DeepCopy() *EmptyDiskSource { + if in == nil { + return nil + } + out := new(EmptyDiskSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EphemeralVolumeSource) DeepCopyInto(out *EphemeralVolumeSource) { + *out = *in + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(corev1.PersistentVolumeClaimVolumeSource) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EphemeralVolumeSource. +func (in *EphemeralVolumeSource) DeepCopy() *EphemeralVolumeSource { + if in == nil { + return nil + } + out := new(EphemeralVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureAPIC) DeepCopyInto(out *FeatureAPIC) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureAPIC. +func (in *FeatureAPIC) DeepCopy() *FeatureAPIC { + if in == nil { + return nil + } + out := new(FeatureAPIC) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureHyperv) DeepCopyInto(out *FeatureHyperv) { + *out = *in + if in.Relaxed != nil { + in, out := &in.Relaxed, &out.Relaxed + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.VAPIC != nil { + in, out := &in.VAPIC, &out.VAPIC + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.Spinlocks != nil { + in, out := &in.Spinlocks, &out.Spinlocks + *out = new(FeatureSpinlocks) + (*in).DeepCopyInto(*out) + } + if in.VPIndex != nil { + in, out := &in.VPIndex, &out.VPIndex + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.SyNIC != nil { + in, out := &in.SyNIC, &out.SyNIC + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.SyNICTimer != nil { + in, out := &in.SyNICTimer, &out.SyNICTimer + *out = new(SyNICTimer) + (*in).DeepCopyInto(*out) + } + if in.Reset != nil { + in, out := &in.Reset, &out.Reset + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.VendorID != nil { + in, out := &in.VendorID, &out.VendorID + *out = new(FeatureVendorID) + (*in).DeepCopyInto(*out) + } + if in.Frequencies != nil { + in, out := &in.Frequencies, &out.Frequencies + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.Reenlightenment != nil { + in, out := &in.Reenlightenment, &out.Reenlightenment + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.TLBFlush != nil { + in, out := &in.TLBFlush, &out.TLBFlush + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.IPI != nil { + in, out := &in.IPI, &out.IPI + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.EVMCS != nil { + in, out := &in.EVMCS, &out.EVMCS + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureHyperv. +func (in *FeatureHyperv) DeepCopy() *FeatureHyperv { + if in == nil { + return nil + } + out := new(FeatureHyperv) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureKVM) DeepCopyInto(out *FeatureKVM) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureKVM. +func (in *FeatureKVM) DeepCopy() *FeatureKVM { + if in == nil { + return nil + } + out := new(FeatureKVM) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureSpinlocks) DeepCopyInto(out *FeatureSpinlocks) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Retries != nil { + in, out := &in.Retries, &out.Retries + *out = new(uint32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureSpinlocks. +func (in *FeatureSpinlocks) DeepCopy() *FeatureSpinlocks { + if in == nil { + return nil + } + out := new(FeatureSpinlocks) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureState) DeepCopyInto(out *FeatureState) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureState. +func (in *FeatureState) DeepCopy() *FeatureState { + if in == nil { + return nil + } + out := new(FeatureState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureVendorID) DeepCopyInto(out *FeatureVendorID) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureVendorID. +func (in *FeatureVendorID) DeepCopy() *FeatureVendorID { + if in == nil { + return nil + } + out := new(FeatureVendorID) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Features) DeepCopyInto(out *Features) { + *out = *in + in.ACPI.DeepCopyInto(&out.ACPI) + if in.APIC != nil { + in, out := &in.APIC, &out.APIC + *out = new(FeatureAPIC) + (*in).DeepCopyInto(*out) + } + if in.Hyperv != nil { + in, out := &in.Hyperv, &out.Hyperv + *out = new(FeatureHyperv) + (*in).DeepCopyInto(*out) + } + if in.SMM != nil { + in, out := &in.SMM, &out.SMM + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + if in.KVM != nil { + in, out := &in.KVM, &out.KVM + *out = new(FeatureKVM) + **out = **in + } + if in.Pvspinlock != nil { + in, out := &in.Pvspinlock, &out.Pvspinlock + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Features. +func (in *Features) DeepCopy() *Features { + if in == nil { + return nil + } + out := new(Features) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Filesystem) DeepCopyInto(out *Filesystem) { + *out = *in + if in.Virtiofs != nil { + in, out := &in.Virtiofs, &out.Virtiofs + *out = new(FilesystemVirtiofs) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Filesystem. +func (in *Filesystem) DeepCopy() *Filesystem { + if in == nil { + return nil + } + out := new(Filesystem) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FilesystemVirtiofs) DeepCopyInto(out *FilesystemVirtiofs) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FilesystemVirtiofs. +func (in *FilesystemVirtiofs) DeepCopy() *FilesystemVirtiofs { + if in == nil { + return nil + } + out := new(FilesystemVirtiofs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Firmware) DeepCopyInto(out *Firmware) { + *out = *in + if in.Bootloader != nil { + in, out := &in.Bootloader, &out.Bootloader + *out = new(Bootloader) + (*in).DeepCopyInto(*out) + } + if in.KernelBoot != nil { + in, out := &in.KernelBoot, &out.KernelBoot + *out = new(KernelBoot) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Firmware. +func (in *Firmware) DeepCopy() *Firmware { + if in == nil { + return nil + } + out := new(Firmware) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Flags) DeepCopyInto(out *Flags) { + *out = *in + if in.API != nil { + in, out := &in.API, &out.API + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Controller != nil { + in, out := &in.Controller, &out.Controller + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Handler != nil { + in, out := &in.Handler, &out.Handler + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flags. +func (in *Flags) DeepCopy() *Flags { + if in == nil { + return nil + } + out := new(Flags) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlavorMatcher) DeepCopyInto(out *FlavorMatcher) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlavorMatcher. +func (in *FlavorMatcher) DeepCopy() *FlavorMatcher { + if in == nil { + return nil + } + out := new(FlavorMatcher) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FreezeUnfreezeTimeout) DeepCopyInto(out *FreezeUnfreezeTimeout) { + *out = *in + if in.UnfreezeTimeout != nil { + in, out := &in.UnfreezeTimeout, &out.UnfreezeTimeout + *out = new(metav1.Duration) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FreezeUnfreezeTimeout. +func (in *FreezeUnfreezeTimeout) DeepCopy() *FreezeUnfreezeTimeout { + if in == nil { + return nil + } + out := new(FreezeUnfreezeTimeout) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GPU) DeepCopyInto(out *GPU) { + *out = *in + if in.VirtualGPUOptions != nil { + in, out := &in.VirtualGPUOptions, &out.VirtualGPUOptions + *out = new(VGPUOptions) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GPU. +func (in *GPU) DeepCopy() *GPU { + if in == nil { + return nil + } + out := new(GPU) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenerationStatus) DeepCopyInto(out *GenerationStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerationStatus. +func (in *GenerationStatus) DeepCopy() *GenerationStatus { + if in == nil { + return nil + } + out := new(GenerationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GuestAgentCommandInfo) DeepCopyInto(out *GuestAgentCommandInfo) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GuestAgentCommandInfo. +func (in *GuestAgentCommandInfo) DeepCopy() *GuestAgentCommandInfo { + if in == nil { + return nil + } + out := new(GuestAgentCommandInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GuestAgentPing) DeepCopyInto(out *GuestAgentPing) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GuestAgentPing. +func (in *GuestAgentPing) DeepCopy() *GuestAgentPing { + if in == nil { + return nil + } + out := new(GuestAgentPing) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HPETTimer) DeepCopyInto(out *HPETTimer) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HPETTimer. +func (in *HPETTimer) DeepCopy() *HPETTimer { + if in == nil { + return nil + } + out := new(HPETTimer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Handler) DeepCopyInto(out *Handler) { + *out = *in + if in.Exec != nil { + in, out := &in.Exec, &out.Exec + *out = new(corev1.ExecAction) + (*in).DeepCopyInto(*out) + } + if in.GuestAgentPing != nil { + in, out := &in.GuestAgentPing, &out.GuestAgentPing + *out = new(GuestAgentPing) + **out = **in + } + if in.HTTPGet != nil { + in, out := &in.HTTPGet, &out.HTTPGet + *out = new(corev1.HTTPGetAction) + (*in).DeepCopyInto(*out) + } + if in.TCPSocket != nil { + in, out := &in.TCPSocket, &out.TCPSocket + *out = new(corev1.TCPSocketAction) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Handler. +func (in *Handler) DeepCopy() *Handler { + if in == nil { + return nil + } + out := new(Handler) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostDevice) DeepCopyInto(out *HostDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostDevice. +func (in *HostDevice) DeepCopy() *HostDevice { + if in == nil { + return nil + } + out := new(HostDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostDisk) DeepCopyInto(out *HostDisk) { + *out = *in + out.Capacity = in.Capacity.DeepCopy() + if in.Shared != nil { + in, out := &in.Shared, &out.Shared + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostDisk. +func (in *HostDisk) DeepCopy() *HostDisk { + if in == nil { + return nil + } + out := new(HostDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HotplugVolumeSource) DeepCopyInto(out *HotplugVolumeSource) { + *out = *in + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(PersistentVolumeClaimVolumeSource) + **out = **in + } + if in.DataVolume != nil { + in, out := &in.DataVolume, &out.DataVolume + *out = new(DataVolumeSource) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HotplugVolumeSource. +func (in *HotplugVolumeSource) DeepCopy() *HotplugVolumeSource { + if in == nil { + return nil + } + out := new(HotplugVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HotplugVolumeStatus) DeepCopyInto(out *HotplugVolumeStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HotplugVolumeStatus. +func (in *HotplugVolumeStatus) DeepCopy() *HotplugVolumeStatus { + if in == nil { + return nil + } + out := new(HotplugVolumeStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Hugepages) DeepCopyInto(out *Hugepages) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Hugepages. +func (in *Hugepages) DeepCopy() *Hugepages { + if in == nil { + return nil + } + out := new(Hugepages) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HypervTimer) DeepCopyInto(out *HypervTimer) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HypervTimer. +func (in *HypervTimer) DeepCopy() *HypervTimer { + if in == nil { + return nil + } + out := new(HypervTimer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *I6300ESBWatchdog) DeepCopyInto(out *I6300ESBWatchdog) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new I6300ESBWatchdog. +func (in *I6300ESBWatchdog) DeepCopy() *I6300ESBWatchdog { + if in == nil { + return nil + } + out := new(I6300ESBWatchdog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Input) DeepCopyInto(out *Input) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Input. +func (in *Input) DeepCopy() *Input { + if in == nil { + return nil + } + out := new(Input) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Interface) DeepCopyInto(out *Interface) { + *out = *in + in.InterfaceBindingMethod.DeepCopyInto(&out.InterfaceBindingMethod) + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]Port, len(*in)) + copy(*out, *in) + } + if in.BootOrder != nil { + in, out := &in.BootOrder, &out.BootOrder + *out = new(uint) + **out = **in + } + if in.DHCPOptions != nil { + in, out := &in.DHCPOptions, &out.DHCPOptions + *out = new(DHCPOptions) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Interface. +func (in *Interface) DeepCopy() *Interface { + if in == nil { + return nil + } + out := new(Interface) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterfaceBindingMethod) DeepCopyInto(out *InterfaceBindingMethod) { + *out = *in + if in.Bridge != nil { + in, out := &in.Bridge, &out.Bridge + *out = new(InterfaceBridge) + **out = **in + } + if in.Slirp != nil { + in, out := &in.Slirp, &out.Slirp + *out = new(InterfaceSlirp) + **out = **in + } + if in.Masquerade != nil { + in, out := &in.Masquerade, &out.Masquerade + *out = new(InterfaceMasquerade) + **out = **in + } + if in.SRIOV != nil { + in, out := &in.SRIOV, &out.SRIOV + *out = new(InterfaceSRIOV) + **out = **in + } + if in.Macvtap != nil { + in, out := &in.Macvtap, &out.Macvtap + *out = new(InterfaceMacvtap) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterfaceBindingMethod. +func (in *InterfaceBindingMethod) DeepCopy() *InterfaceBindingMethod { + if in == nil { + return nil + } + out := new(InterfaceBindingMethod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterfaceBridge) DeepCopyInto(out *InterfaceBridge) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterfaceBridge. +func (in *InterfaceBridge) DeepCopy() *InterfaceBridge { + if in == nil { + return nil + } + out := new(InterfaceBridge) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterfaceMacvtap) DeepCopyInto(out *InterfaceMacvtap) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterfaceMacvtap. +func (in *InterfaceMacvtap) DeepCopy() *InterfaceMacvtap { + if in == nil { + return nil + } + out := new(InterfaceMacvtap) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterfaceMasquerade) DeepCopyInto(out *InterfaceMasquerade) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterfaceMasquerade. +func (in *InterfaceMasquerade) DeepCopy() *InterfaceMasquerade { + if in == nil { + return nil + } + out := new(InterfaceMasquerade) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterfaceSRIOV) DeepCopyInto(out *InterfaceSRIOV) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterfaceSRIOV. +func (in *InterfaceSRIOV) DeepCopy() *InterfaceSRIOV { + if in == nil { + return nil + } + out := new(InterfaceSRIOV) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterfaceSlirp) DeepCopyInto(out *InterfaceSlirp) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterfaceSlirp. +func (in *InterfaceSlirp) DeepCopy() *InterfaceSlirp { + if in == nil { + return nil + } + out := new(InterfaceSlirp) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KVMTimer) DeepCopyInto(out *KVMTimer) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KVMTimer. +func (in *KVMTimer) DeepCopy() *KVMTimer { + if in == nil { + return nil + } + out := new(KVMTimer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KernelBoot) DeepCopyInto(out *KernelBoot) { + *out = *in + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(KernelBootContainer) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KernelBoot. +func (in *KernelBoot) DeepCopy() *KernelBoot { + if in == nil { + return nil + } + out := new(KernelBoot) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KernelBootContainer) DeepCopyInto(out *KernelBootContainer) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KernelBootContainer. +func (in *KernelBootContainer) DeepCopy() *KernelBootContainer { + if in == nil { + return nil + } + out := new(KernelBootContainer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirt) DeepCopyInto(out *KubeVirt) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirt. +func (in *KubeVirt) DeepCopy() *KubeVirt { + if in == nil { + return nil + } + out := new(KubeVirt) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeVirt) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtCertificateRotateStrategy) DeepCopyInto(out *KubeVirtCertificateRotateStrategy) { + *out = *in + if in.SelfSigned != nil { + in, out := &in.SelfSigned, &out.SelfSigned + *out = new(KubeVirtSelfSignConfiguration) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtCertificateRotateStrategy. +func (in *KubeVirtCertificateRotateStrategy) DeepCopy() *KubeVirtCertificateRotateStrategy { + if in == nil { + return nil + } + out := new(KubeVirtCertificateRotateStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtCondition) DeepCopyInto(out *KubeVirtCondition) { + *out = *in + in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtCondition. +func (in *KubeVirtCondition) DeepCopy() *KubeVirtCondition { + if in == nil { + return nil + } + out := new(KubeVirtCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtConfiguration) DeepCopyInto(out *KubeVirtConfiguration) { + *out = *in + if in.CPURequest != nil { + in, out := &in.CPURequest, &out.CPURequest + x := (*in).DeepCopy() + *out = &x + } + if in.DeveloperConfiguration != nil { + in, out := &in.DeveloperConfiguration, &out.DeveloperConfiguration + *out = new(DeveloperConfiguration) + (*in).DeepCopyInto(*out) + } + if in.EmulatedMachines != nil { + in, out := &in.EmulatedMachines, &out.EmulatedMachines + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.MigrationConfiguration != nil { + in, out := &in.MigrationConfiguration, &out.MigrationConfiguration + *out = new(MigrationConfiguration) + (*in).DeepCopyInto(*out) + } + if in.NetworkConfiguration != nil { + in, out := &in.NetworkConfiguration, &out.NetworkConfiguration + *out = new(NetworkConfiguration) + (*in).DeepCopyInto(*out) + } + if in.SMBIOSConfig != nil { + in, out := &in.SMBIOSConfig, &out.SMBIOSConfig + *out = new(SMBiosConfiguration) + **out = **in + } + if in.EvictionStrategy != nil { + in, out := &in.EvictionStrategy, &out.EvictionStrategy + *out = new(EvictionStrategy) + **out = **in + } + if in.SupportedGuestAgentVersions != nil { + in, out := &in.SupportedGuestAgentVersions, &out.SupportedGuestAgentVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.MemBalloonStatsPeriod != nil { + in, out := &in.MemBalloonStatsPeriod, &out.MemBalloonStatsPeriod + *out = new(uint32) + **out = **in + } + if in.PermittedHostDevices != nil { + in, out := &in.PermittedHostDevices, &out.PermittedHostDevices + *out = new(PermittedHostDevices) + (*in).DeepCopyInto(*out) + } + if in.MediatedDevicesConfiguration != nil { + in, out := &in.MediatedDevicesConfiguration, &out.MediatedDevicesConfiguration + *out = new(MediatedDevicesConfiguration) + (*in).DeepCopyInto(*out) + } + if in.ObsoleteCPUModels != nil { + in, out := &in.ObsoleteCPUModels, &out.ObsoleteCPUModels + *out = make(map[string]bool, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.VirtualMachineInstancesPerNode != nil { + in, out := &in.VirtualMachineInstancesPerNode, &out.VirtualMachineInstancesPerNode + *out = new(int) + **out = **in + } + if in.APIConfiguration != nil { + in, out := &in.APIConfiguration, &out.APIConfiguration + *out = new(ReloadableComponentConfiguration) + (*in).DeepCopyInto(*out) + } + if in.WebhookConfiguration != nil { + in, out := &in.WebhookConfiguration, &out.WebhookConfiguration + *out = new(ReloadableComponentConfiguration) + (*in).DeepCopyInto(*out) + } + if in.ControllerConfiguration != nil { + in, out := &in.ControllerConfiguration, &out.ControllerConfiguration + *out = new(ReloadableComponentConfiguration) + (*in).DeepCopyInto(*out) + } + if in.HandlerConfiguration != nil { + in, out := &in.HandlerConfiguration, &out.HandlerConfiguration + *out = new(ReloadableComponentConfiguration) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtConfiguration. +func (in *KubeVirtConfiguration) DeepCopy() *KubeVirtConfiguration { + if in == nil { + return nil + } + out := new(KubeVirtConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtList) DeepCopyInto(out *KubeVirtList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KubeVirt, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtList. +func (in *KubeVirtList) DeepCopy() *KubeVirtList { + if in == nil { + return nil + } + out := new(KubeVirtList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeVirtList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtSelfSignConfiguration) DeepCopyInto(out *KubeVirtSelfSignConfiguration) { + *out = *in + if in.CARotateInterval != nil { + in, out := &in.CARotateInterval, &out.CARotateInterval + *out = new(metav1.Duration) + **out = **in + } + if in.CertRotateInterval != nil { + in, out := &in.CertRotateInterval, &out.CertRotateInterval + *out = new(metav1.Duration) + **out = **in + } + if in.CAOverlapInterval != nil { + in, out := &in.CAOverlapInterval, &out.CAOverlapInterval + *out = new(metav1.Duration) + **out = **in + } + if in.CA != nil { + in, out := &in.CA, &out.CA + *out = new(CertConfig) + (*in).DeepCopyInto(*out) + } + if in.Server != nil { + in, out := &in.Server, &out.Server + *out = new(CertConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtSelfSignConfiguration. +func (in *KubeVirtSelfSignConfiguration) DeepCopy() *KubeVirtSelfSignConfiguration { + if in == nil { + return nil + } + out := new(KubeVirtSelfSignConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtSpec) DeepCopyInto(out *KubeVirtSpec) { + *out = *in + in.WorkloadUpdateStrategy.DeepCopyInto(&out.WorkloadUpdateStrategy) + in.CertificateRotationStrategy.DeepCopyInto(&out.CertificateRotationStrategy) + in.Configuration.DeepCopyInto(&out.Configuration) + if in.Infra != nil { + in, out := &in.Infra, &out.Infra + *out = new(ComponentConfig) + (*in).DeepCopyInto(*out) + } + if in.Workloads != nil { + in, out := &in.Workloads, &out.Workloads + *out = new(ComponentConfig) + (*in).DeepCopyInto(*out) + } + in.CustomizeComponents.DeepCopyInto(&out.CustomizeComponents) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtSpec. +func (in *KubeVirtSpec) DeepCopy() *KubeVirtSpec { + if in == nil { + return nil + } + out := new(KubeVirtSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtStatus) DeepCopyInto(out *KubeVirtStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]KubeVirtCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.OutdatedVirtualMachineInstanceWorkloads != nil { + in, out := &in.OutdatedVirtualMachineInstanceWorkloads, &out.OutdatedVirtualMachineInstanceWorkloads + *out = new(int) + **out = **in + } + if in.ObservedGeneration != nil { + in, out := &in.ObservedGeneration, &out.ObservedGeneration + *out = new(int64) + **out = **in + } + if in.Generations != nil { + in, out := &in.Generations, &out.Generations + *out = make([]GenerationStatus, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtStatus. +func (in *KubeVirtStatus) DeepCopy() *KubeVirtStatus { + if in == nil { + return nil + } + out := new(KubeVirtStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeVirtWorkloadUpdateStrategy) DeepCopyInto(out *KubeVirtWorkloadUpdateStrategy) { + *out = *in + if in.WorkloadUpdateMethods != nil { + in, out := &in.WorkloadUpdateMethods, &out.WorkloadUpdateMethods + *out = make([]WorkloadUpdateMethod, len(*in)) + copy(*out, *in) + } + if in.BatchEvictionSize != nil { + in, out := &in.BatchEvictionSize, &out.BatchEvictionSize + *out = new(int) + **out = **in + } + if in.BatchEvictionInterval != nil { + in, out := &in.BatchEvictionInterval, &out.BatchEvictionInterval + *out = new(metav1.Duration) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeVirtWorkloadUpdateStrategy. +func (in *KubeVirtWorkloadUpdateStrategy) DeepCopy() *KubeVirtWorkloadUpdateStrategy { + if in == nil { + return nil + } + out := new(KubeVirtWorkloadUpdateStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LaunchSecurity) DeepCopyInto(out *LaunchSecurity) { + *out = *in + if in.SEV != nil { + in, out := &in.SEV, &out.SEV + *out = new(SEV) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LaunchSecurity. +func (in *LaunchSecurity) DeepCopy() *LaunchSecurity { + if in == nil { + return nil + } + out := new(LaunchSecurity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LogVerbosity) DeepCopyInto(out *LogVerbosity) { + *out = *in + if in.NodeVerbosity != nil { + in, out := &in.NodeVerbosity, &out.NodeVerbosity + *out = make(map[string]uint, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogVerbosity. +func (in *LogVerbosity) DeepCopy() *LogVerbosity { + if in == nil { + return nil + } + out := new(LogVerbosity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LunTarget) DeepCopyInto(out *LunTarget) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LunTarget. +func (in *LunTarget) DeepCopy() *LunTarget { + if in == nil { + return nil + } + out := new(LunTarget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Machine) DeepCopyInto(out *Machine) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Machine. +func (in *Machine) DeepCopy() *Machine { + if in == nil { + return nil + } + out := new(Machine) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MediatedDevicesConfiguration) DeepCopyInto(out *MediatedDevicesConfiguration) { + *out = *in + if in.MediatedDevicesTypes != nil { + in, out := &in.MediatedDevicesTypes, &out.MediatedDevicesTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.NodeMediatedDeviceTypes != nil { + in, out := &in.NodeMediatedDeviceTypes, &out.NodeMediatedDeviceTypes + *out = make([]NodeMediatedDeviceTypesConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MediatedDevicesConfiguration. +func (in *MediatedDevicesConfiguration) DeepCopy() *MediatedDevicesConfiguration { + if in == nil { + return nil + } + out := new(MediatedDevicesConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MediatedHostDevice) DeepCopyInto(out *MediatedHostDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MediatedHostDevice. +func (in *MediatedHostDevice) DeepCopy() *MediatedHostDevice { + if in == nil { + return nil + } + out := new(MediatedHostDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Memory) DeepCopyInto(out *Memory) { + *out = *in + if in.Hugepages != nil { + in, out := &in.Hugepages, &out.Hugepages + *out = new(Hugepages) + **out = **in + } + if in.Guest != nil { + in, out := &in.Guest, &out.Guest + x := (*in).DeepCopy() + *out = &x + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memory. +func (in *Memory) DeepCopy() *Memory { + if in == nil { + return nil + } + out := new(Memory) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemoryDumpVolumeSource) DeepCopyInto(out *MemoryDumpVolumeSource) { + *out = *in + out.PersistentVolumeClaimVolumeSource = in.PersistentVolumeClaimVolumeSource + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemoryDumpVolumeSource. +func (in *MemoryDumpVolumeSource) DeepCopy() *MemoryDumpVolumeSource { + if in == nil { + return nil + } + out := new(MemoryDumpVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MigrateOptions) DeepCopyInto(out *MigrateOptions) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MigrateOptions. +func (in *MigrateOptions) DeepCopy() *MigrateOptions { + if in == nil { + return nil + } + out := new(MigrateOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MigrationConfiguration) DeepCopyInto(out *MigrationConfiguration) { + *out = *in + if in.NodeDrainTaintKey != nil { + in, out := &in.NodeDrainTaintKey, &out.NodeDrainTaintKey + *out = new(string) + **out = **in + } + if in.ParallelOutboundMigrationsPerNode != nil { + in, out := &in.ParallelOutboundMigrationsPerNode, &out.ParallelOutboundMigrationsPerNode + *out = new(uint32) + **out = **in + } + if in.ParallelMigrationsPerCluster != nil { + in, out := &in.ParallelMigrationsPerCluster, &out.ParallelMigrationsPerCluster + *out = new(uint32) + **out = **in + } + if in.AllowAutoConverge != nil { + in, out := &in.AllowAutoConverge, &out.AllowAutoConverge + *out = new(bool) + **out = **in + } + if in.BandwidthPerMigration != nil { + in, out := &in.BandwidthPerMigration, &out.BandwidthPerMigration + x := (*in).DeepCopy() + *out = &x + } + if in.CompletionTimeoutPerGiB != nil { + in, out := &in.CompletionTimeoutPerGiB, &out.CompletionTimeoutPerGiB + *out = new(int64) + **out = **in + } + if in.ProgressTimeout != nil { + in, out := &in.ProgressTimeout, &out.ProgressTimeout + *out = new(int64) + **out = **in + } + if in.UnsafeMigrationOverride != nil { + in, out := &in.UnsafeMigrationOverride, &out.UnsafeMigrationOverride + *out = new(bool) + **out = **in + } + if in.AllowPostCopy != nil { + in, out := &in.AllowPostCopy, &out.AllowPostCopy + *out = new(bool) + **out = **in + } + if in.DisableTLS != nil { + in, out := &in.DisableTLS, &out.DisableTLS + *out = new(bool) + **out = **in + } + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MigrationConfiguration. +func (in *MigrationConfiguration) DeepCopy() *MigrationConfiguration { + if in == nil { + return nil + } + out := new(MigrationConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MultusNetwork) DeepCopyInto(out *MultusNetwork) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MultusNetwork. +func (in *MultusNetwork) DeepCopy() *MultusNetwork { + if in == nil { + return nil + } + out := new(MultusNetwork) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NUMA) DeepCopyInto(out *NUMA) { + *out = *in + if in.GuestMappingPassthrough != nil { + in, out := &in.GuestMappingPassthrough, &out.GuestMappingPassthrough + *out = new(NUMAGuestMappingPassthrough) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NUMA. +func (in *NUMA) DeepCopy() *NUMA { + if in == nil { + return nil + } + out := new(NUMA) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NUMAGuestMappingPassthrough) DeepCopyInto(out *NUMAGuestMappingPassthrough) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NUMAGuestMappingPassthrough. +func (in *NUMAGuestMappingPassthrough) DeepCopy() *NUMAGuestMappingPassthrough { + if in == nil { + return nil + } + out := new(NUMAGuestMappingPassthrough) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Network) DeepCopyInto(out *Network) { + *out = *in + in.NetworkSource.DeepCopyInto(&out.NetworkSource) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network. +func (in *Network) DeepCopy() *Network { + if in == nil { + return nil + } + out := new(Network) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkConfiguration) DeepCopyInto(out *NetworkConfiguration) { + *out = *in + if in.PermitSlirpInterface != nil { + in, out := &in.PermitSlirpInterface, &out.PermitSlirpInterface + *out = new(bool) + **out = **in + } + if in.PermitBridgeInterfaceOnPodNetwork != nil { + in, out := &in.PermitBridgeInterfaceOnPodNetwork, &out.PermitBridgeInterfaceOnPodNetwork + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConfiguration. +func (in *NetworkConfiguration) DeepCopy() *NetworkConfiguration { + if in == nil { + return nil + } + out := new(NetworkConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSource) DeepCopyInto(out *NetworkSource) { + *out = *in + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + *out = new(PodNetwork) + **out = **in + } + if in.Multus != nil { + in, out := &in.Multus, &out.Multus + *out = new(MultusNetwork) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSource. +func (in *NetworkSource) DeepCopy() *NetworkSource { + if in == nil { + return nil + } + out := new(NetworkSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeMediatedDeviceTypesConfig) DeepCopyInto(out *NodeMediatedDeviceTypesConfig) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MediatedDevicesTypes != nil { + in, out := &in.MediatedDevicesTypes, &out.MediatedDevicesTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeMediatedDeviceTypesConfig. +func (in *NodeMediatedDeviceTypesConfig) DeepCopy() *NodeMediatedDeviceTypesConfig { + if in == nil { + return nil + } + out := new(NodeMediatedDeviceTypesConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodePlacement) DeepCopyInto(out *NodePlacement) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(corev1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodePlacement. +func (in *NodePlacement) DeepCopy() *NodePlacement { + if in == nil { + return nil + } + out := new(NodePlacement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PITTimer) DeepCopyInto(out *PITTimer) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PITTimer. +func (in *PITTimer) DeepCopy() *PITTimer { + if in == nil { + return nil + } + out := new(PITTimer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PauseOptions) DeepCopyInto(out *PauseOptions) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PauseOptions. +func (in *PauseOptions) DeepCopy() *PauseOptions { + if in == nil { + return nil + } + out := new(PauseOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PciHostDevice) DeepCopyInto(out *PciHostDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PciHostDevice. +func (in *PciHostDevice) DeepCopy() *PciHostDevice { + if in == nil { + return nil + } + out := new(PciHostDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PermittedHostDevices) DeepCopyInto(out *PermittedHostDevices) { + *out = *in + if in.PciHostDevices != nil { + in, out := &in.PciHostDevices, &out.PciHostDevices + *out = make([]PciHostDevice, len(*in)) + copy(*out, *in) + } + if in.MediatedDevices != nil { + in, out := &in.MediatedDevices, &out.MediatedDevices + *out = make([]MediatedHostDevice, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PermittedHostDevices. +func (in *PermittedHostDevices) DeepCopy() *PermittedHostDevices { + if in == nil { + return nil + } + out := new(PermittedHostDevices) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersistentVolumeClaimInfo) DeepCopyInto(out *PersistentVolumeClaimInfo) { + *out = *in + if in.AccessModes != nil { + in, out := &in.AccessModes, &out.AccessModes + *out = make([]corev1.PersistentVolumeAccessMode, len(*in)) + copy(*out, *in) + } + if in.VolumeMode != nil { + in, out := &in.VolumeMode, &out.VolumeMode + *out = new(corev1.PersistentVolumeMode) + **out = **in + } + if in.Capacity != nil { + in, out := &in.Capacity, &out.Capacity + *out = make(corev1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.Requests != nil { + in, out := &in.Requests, &out.Requests + *out = make(corev1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.FilesystemOverhead != nil { + in, out := &in.FilesystemOverhead, &out.FilesystemOverhead + *out = new(v1beta1.Percent) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeClaimInfo. +func (in *PersistentVolumeClaimInfo) DeepCopy() *PersistentVolumeClaimInfo { + if in == nil { + return nil + } + out := new(PersistentVolumeClaimInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersistentVolumeClaimVolumeSource) DeepCopyInto(out *PersistentVolumeClaimVolumeSource) { + *out = *in + out.PersistentVolumeClaimVolumeSource = in.PersistentVolumeClaimVolumeSource + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeClaimVolumeSource. +func (in *PersistentVolumeClaimVolumeSource) DeepCopy() *PersistentVolumeClaimVolumeSource { + if in == nil { + return nil + } + out := new(PersistentVolumeClaimVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodNetwork) DeepCopyInto(out *PodNetwork) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodNetwork. +func (in *PodNetwork) DeepCopy() *PodNetwork { + if in == nil { + return nil + } + out := new(PodNetwork) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Port) DeepCopyInto(out *Port) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Port. +func (in *Port) DeepCopy() *Port { + if in == nil { + return nil + } + out := new(Port) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PreferenceMatcher) DeepCopyInto(out *PreferenceMatcher) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreferenceMatcher. +func (in *PreferenceMatcher) DeepCopy() *PreferenceMatcher { + if in == nil { + return nil + } + out := new(PreferenceMatcher) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Probe) DeepCopyInto(out *Probe) { + *out = *in + in.Handler.DeepCopyInto(&out.Handler) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Probe. +func (in *Probe) DeepCopy() *Probe { + if in == nil { + return nil + } + out := new(Probe) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfilerResult) DeepCopyInto(out *ProfilerResult) { + *out = *in + if in.PprofData != nil { + in, out := &in.PprofData, &out.PprofData + *out = make(map[string][]byte, len(*in)) + for key, val := range *in { + var outVal []byte + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]byte, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfilerResult. +func (in *ProfilerResult) DeepCopy() *ProfilerResult { + if in == nil { + return nil + } + out := new(ProfilerResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *QemuGuestAgentSSHPublicKeyAccessCredentialPropagation) DeepCopyInto(out *QemuGuestAgentSSHPublicKeyAccessCredentialPropagation) { + *out = *in + if in.Users != nil { + in, out := &in.Users, &out.Users + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QemuGuestAgentSSHPublicKeyAccessCredentialPropagation. +func (in *QemuGuestAgentSSHPublicKeyAccessCredentialPropagation) DeepCopy() *QemuGuestAgentSSHPublicKeyAccessCredentialPropagation { + if in == nil { + return nil + } + out := new(QemuGuestAgentSSHPublicKeyAccessCredentialPropagation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *QemuGuestAgentUserPasswordAccessCredentialPropagation) DeepCopyInto(out *QemuGuestAgentUserPasswordAccessCredentialPropagation) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QemuGuestAgentUserPasswordAccessCredentialPropagation. +func (in *QemuGuestAgentUserPasswordAccessCredentialPropagation) DeepCopy() *QemuGuestAgentUserPasswordAccessCredentialPropagation { + if in == nil { + return nil + } + out := new(QemuGuestAgentUserPasswordAccessCredentialPropagation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RESTClientConfiguration) DeepCopyInto(out *RESTClientConfiguration) { + *out = *in + if in.RateLimiter != nil { + in, out := &in.RateLimiter, &out.RateLimiter + *out = new(RateLimiter) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RESTClientConfiguration. +func (in *RESTClientConfiguration) DeepCopy() *RESTClientConfiguration { + if in == nil { + return nil + } + out := new(RESTClientConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RTCTimer) DeepCopyInto(out *RTCTimer) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RTCTimer. +func (in *RTCTimer) DeepCopy() *RTCTimer { + if in == nil { + return nil + } + out := new(RTCTimer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimiter) DeepCopyInto(out *RateLimiter) { + *out = *in + if in.TokenBucketRateLimiter != nil { + in, out := &in.TokenBucketRateLimiter, &out.TokenBucketRateLimiter + *out = new(TokenBucketRateLimiter) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimiter. +func (in *RateLimiter) DeepCopy() *RateLimiter { + if in == nil { + return nil + } + out := new(RateLimiter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Realtime) DeepCopyInto(out *Realtime) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Realtime. +func (in *Realtime) DeepCopy() *Realtime { + if in == nil { + return nil + } + out := new(Realtime) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReloadableComponentConfiguration) DeepCopyInto(out *ReloadableComponentConfiguration) { + *out = *in + if in.RestClient != nil { + in, out := &in.RestClient, &out.RestClient + *out = new(RESTClientConfiguration) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReloadableComponentConfiguration. +func (in *ReloadableComponentConfiguration) DeepCopy() *ReloadableComponentConfiguration { + if in == nil { + return nil + } + out := new(ReloadableComponentConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoveVolumeOptions) DeepCopyInto(out *RemoveVolumeOptions) { + *out = *in + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoveVolumeOptions. +func (in *RemoveVolumeOptions) DeepCopy() *RemoveVolumeOptions { + if in == nil { + return nil + } + out := new(RemoveVolumeOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRequirements) DeepCopyInto(out *ResourceRequirements) { + *out = *in + if in.Requests != nil { + in, out := &in.Requests, &out.Requests + *out = make(corev1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = make(corev1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRequirements. +func (in *ResourceRequirements) DeepCopy() *ResourceRequirements { + if in == nil { + return nil + } + out := new(ResourceRequirements) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestartOptions) DeepCopyInto(out *RestartOptions) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.GracePeriodSeconds != nil { + in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds + *out = new(int64) + **out = **in + } + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestartOptions. +func (in *RestartOptions) DeepCopy() *RestartOptions { + if in == nil { + return nil + } + out := new(RestartOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Rng) DeepCopyInto(out *Rng) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rng. +func (in *Rng) DeepCopy() *Rng { + if in == nil { + return nil + } + out := new(Rng) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SEV) DeepCopyInto(out *SEV) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SEV. +func (in *SEV) DeepCopy() *SEV { + if in == nil { + return nil + } + out := new(SEV) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SMBiosConfiguration) DeepCopyInto(out *SMBiosConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SMBiosConfiguration. +func (in *SMBiosConfiguration) DeepCopy() *SMBiosConfiguration { + if in == nil { + return nil + } + out := new(SMBiosConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SSHPublicKeyAccessCredential) DeepCopyInto(out *SSHPublicKeyAccessCredential) { + *out = *in + in.Source.DeepCopyInto(&out.Source) + in.PropagationMethod.DeepCopyInto(&out.PropagationMethod) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SSHPublicKeyAccessCredential. +func (in *SSHPublicKeyAccessCredential) DeepCopy() *SSHPublicKeyAccessCredential { + if in == nil { + return nil + } + out := new(SSHPublicKeyAccessCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SSHPublicKeyAccessCredentialPropagationMethod) DeepCopyInto(out *SSHPublicKeyAccessCredentialPropagationMethod) { + *out = *in + if in.ConfigDrive != nil { + in, out := &in.ConfigDrive, &out.ConfigDrive + *out = new(ConfigDriveSSHPublicKeyAccessCredentialPropagation) + **out = **in + } + if in.QemuGuestAgent != nil { + in, out := &in.QemuGuestAgent, &out.QemuGuestAgent + *out = new(QemuGuestAgentSSHPublicKeyAccessCredentialPropagation) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SSHPublicKeyAccessCredentialPropagationMethod. +func (in *SSHPublicKeyAccessCredentialPropagationMethod) DeepCopy() *SSHPublicKeyAccessCredentialPropagationMethod { + if in == nil { + return nil + } + out := new(SSHPublicKeyAccessCredentialPropagationMethod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SSHPublicKeyAccessCredentialSource) DeepCopyInto(out *SSHPublicKeyAccessCredentialSource) { + *out = *in + if in.Secret != nil { + in, out := &in.Secret, &out.Secret + *out = new(AccessCredentialSecretSource) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SSHPublicKeyAccessCredentialSource. +func (in *SSHPublicKeyAccessCredentialSource) DeepCopy() *SSHPublicKeyAccessCredentialSource { + if in == nil { + return nil + } + out := new(SSHPublicKeyAccessCredentialSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretVolumeSource) DeepCopyInto(out *SecretVolumeSource) { + *out = *in + if in.Optional != nil { + in, out := &in.Optional, &out.Optional + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretVolumeSource. +func (in *SecretVolumeSource) DeepCopy() *SecretVolumeSource { + if in == nil { + return nil + } + out := new(SecretVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountVolumeSource) DeepCopyInto(out *ServiceAccountVolumeSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountVolumeSource. +func (in *ServiceAccountVolumeSource) DeepCopy() *ServiceAccountVolumeSource { + if in == nil { + return nil + } + out := new(ServiceAccountVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SoundDevice) DeepCopyInto(out *SoundDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SoundDevice. +func (in *SoundDevice) DeepCopy() *SoundDevice { + if in == nil { + return nil + } + out := new(SoundDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StartOptions) DeepCopyInto(out *StartOptions) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StartOptions. +func (in *StartOptions) DeepCopy() *StartOptions { + if in == nil { + return nil + } + out := new(StartOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StopOptions) DeepCopyInto(out *StopOptions) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.GracePeriod != nil { + in, out := &in.GracePeriod, &out.GracePeriod + *out = new(int64) + **out = **in + } + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StopOptions. +func (in *StopOptions) DeepCopy() *StopOptions { + if in == nil { + return nil + } + out := new(StopOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SyNICTimer) DeepCopyInto(out *SyNICTimer) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Direct != nil { + in, out := &in.Direct, &out.Direct + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyNICTimer. +func (in *SyNICTimer) DeepCopy() *SyNICTimer { + if in == nil { + return nil + } + out := new(SyNICTimer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SysprepSource) DeepCopyInto(out *SysprepSource) { + *out = *in + if in.Secret != nil { + in, out := &in.Secret, &out.Secret + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap + *out = new(corev1.LocalObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SysprepSource. +func (in *SysprepSource) DeepCopy() *SysprepSource { + if in == nil { + return nil + } + out := new(SysprepSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TPMDevice) DeepCopyInto(out *TPMDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TPMDevice. +func (in *TPMDevice) DeepCopy() *TPMDevice { + if in == nil { + return nil + } + out := new(TPMDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Timer) DeepCopyInto(out *Timer) { + *out = *in + if in.HPET != nil { + in, out := &in.HPET, &out.HPET + *out = new(HPETTimer) + (*in).DeepCopyInto(*out) + } + if in.KVM != nil { + in, out := &in.KVM, &out.KVM + *out = new(KVMTimer) + (*in).DeepCopyInto(*out) + } + if in.PIT != nil { + in, out := &in.PIT, &out.PIT + *out = new(PITTimer) + (*in).DeepCopyInto(*out) + } + if in.RTC != nil { + in, out := &in.RTC, &out.RTC + *out = new(RTCTimer) + (*in).DeepCopyInto(*out) + } + if in.Hyperv != nil { + in, out := &in.Hyperv, &out.Hyperv + *out = new(HypervTimer) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Timer. +func (in *Timer) DeepCopy() *Timer { + if in == nil { + return nil + } + out := new(Timer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TokenBucketRateLimiter) DeepCopyInto(out *TokenBucketRateLimiter) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenBucketRateLimiter. +func (in *TokenBucketRateLimiter) DeepCopy() *TokenBucketRateLimiter { + if in == nil { + return nil + } + out := new(TokenBucketRateLimiter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologyHints) DeepCopyInto(out *TopologyHints) { + *out = *in + if in.TSCFrequency != nil { + in, out := &in.TSCFrequency, &out.TSCFrequency + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologyHints. +func (in *TopologyHints) DeepCopy() *TopologyHints { + if in == nil { + return nil + } + out := new(TopologyHints) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UnpauseOptions) DeepCopyInto(out *UnpauseOptions) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.DryRun != nil { + in, out := &in.DryRun, &out.DryRun + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnpauseOptions. +func (in *UnpauseOptions) DeepCopy() *UnpauseOptions { + if in == nil { + return nil + } + out := new(UnpauseOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UserPasswordAccessCredential) DeepCopyInto(out *UserPasswordAccessCredential) { + *out = *in + in.Source.DeepCopyInto(&out.Source) + in.PropagationMethod.DeepCopyInto(&out.PropagationMethod) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserPasswordAccessCredential. +func (in *UserPasswordAccessCredential) DeepCopy() *UserPasswordAccessCredential { + if in == nil { + return nil + } + out := new(UserPasswordAccessCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UserPasswordAccessCredentialPropagationMethod) DeepCopyInto(out *UserPasswordAccessCredentialPropagationMethod) { + *out = *in + if in.QemuGuestAgent != nil { + in, out := &in.QemuGuestAgent, &out.QemuGuestAgent + *out = new(QemuGuestAgentUserPasswordAccessCredentialPropagation) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserPasswordAccessCredentialPropagationMethod. +func (in *UserPasswordAccessCredentialPropagationMethod) DeepCopy() *UserPasswordAccessCredentialPropagationMethod { + if in == nil { + return nil + } + out := new(UserPasswordAccessCredentialPropagationMethod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UserPasswordAccessCredentialSource) DeepCopyInto(out *UserPasswordAccessCredentialSource) { + *out = *in + if in.Secret != nil { + in, out := &in.Secret, &out.Secret + *out = new(AccessCredentialSecretSource) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserPasswordAccessCredentialSource. +func (in *UserPasswordAccessCredentialSource) DeepCopy() *UserPasswordAccessCredentialSource { + if in == nil { + return nil + } + out := new(UserPasswordAccessCredentialSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VGPUDisplayOptions) DeepCopyInto(out *VGPUDisplayOptions) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.RamFB != nil { + in, out := &in.RamFB, &out.RamFB + *out = new(FeatureState) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VGPUDisplayOptions. +func (in *VGPUDisplayOptions) DeepCopy() *VGPUDisplayOptions { + if in == nil { + return nil + } + out := new(VGPUDisplayOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VGPUOptions) DeepCopyInto(out *VGPUOptions) { + *out = *in + if in.Display != nil { + in, out := &in.Display, &out.Display + *out = new(VGPUDisplayOptions) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VGPUOptions. +func (in *VGPUOptions) DeepCopy() *VGPUOptions { + if in == nil { + return nil + } + out := new(VGPUOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VMISelector) DeepCopyInto(out *VMISelector) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMISelector. +func (in *VMISelector) DeepCopy() *VMISelector { + if in == nil { + return nil + } + out := new(VMISelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachine) DeepCopyInto(out *VirtualMachine) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachine. +func (in *VirtualMachine) DeepCopy() *VirtualMachine { + if in == nil { + return nil + } + out := new(VirtualMachine) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachine) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineCondition) DeepCopyInto(out *VirtualMachineCondition) { + *out = *in + in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineCondition. +func (in *VirtualMachineCondition) DeepCopy() *VirtualMachineCondition { + if in == nil { + return nil + } + out := new(VirtualMachineCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstance) DeepCopyInto(out *VirtualMachineInstance) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstance. +func (in *VirtualMachineInstance) DeepCopy() *VirtualMachineInstance { + if in == nil { + return nil + } + out := new(VirtualMachineInstance) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstance) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceCondition) DeepCopyInto(out *VirtualMachineInstanceCondition) { + *out = *in + in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceCondition. +func (in *VirtualMachineInstanceCondition) DeepCopy() *VirtualMachineInstanceCondition { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceFileSystem) DeepCopyInto(out *VirtualMachineInstanceFileSystem) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceFileSystem. +func (in *VirtualMachineInstanceFileSystem) DeepCopy() *VirtualMachineInstanceFileSystem { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceFileSystem) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceFileSystemInfo) DeepCopyInto(out *VirtualMachineInstanceFileSystemInfo) { + *out = *in + if in.Filesystems != nil { + in, out := &in.Filesystems, &out.Filesystems + *out = make([]VirtualMachineInstanceFileSystem, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceFileSystemInfo. +func (in *VirtualMachineInstanceFileSystemInfo) DeepCopy() *VirtualMachineInstanceFileSystemInfo { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceFileSystemInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceFileSystemList) DeepCopyInto(out *VirtualMachineInstanceFileSystemList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachineInstanceFileSystem, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceFileSystemList. +func (in *VirtualMachineInstanceFileSystemList) DeepCopy() *VirtualMachineInstanceFileSystemList { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceFileSystemList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceFileSystemList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceGuestAgentInfo) DeepCopyInto(out *VirtualMachineInstanceGuestAgentInfo) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.SupportedCommands != nil { + in, out := &in.SupportedCommands, &out.SupportedCommands + *out = make([]GuestAgentCommandInfo, len(*in)) + copy(*out, *in) + } + out.OS = in.OS + if in.UserList != nil { + in, out := &in.UserList, &out.UserList + *out = make([]VirtualMachineInstanceGuestOSUser, len(*in)) + copy(*out, *in) + } + in.FSInfo.DeepCopyInto(&out.FSInfo) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceGuestAgentInfo. +func (in *VirtualMachineInstanceGuestAgentInfo) DeepCopy() *VirtualMachineInstanceGuestAgentInfo { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceGuestAgentInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceGuestAgentInfo) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceGuestOSInfo) DeepCopyInto(out *VirtualMachineInstanceGuestOSInfo) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceGuestOSInfo. +func (in *VirtualMachineInstanceGuestOSInfo) DeepCopy() *VirtualMachineInstanceGuestOSInfo { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceGuestOSInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceGuestOSUser) DeepCopyInto(out *VirtualMachineInstanceGuestOSUser) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceGuestOSUser. +func (in *VirtualMachineInstanceGuestOSUser) DeepCopy() *VirtualMachineInstanceGuestOSUser { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceGuestOSUser) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceGuestOSUserList) DeepCopyInto(out *VirtualMachineInstanceGuestOSUserList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachineInstanceGuestOSUser, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceGuestOSUserList. +func (in *VirtualMachineInstanceGuestOSUserList) DeepCopy() *VirtualMachineInstanceGuestOSUserList { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceGuestOSUserList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceGuestOSUserList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceList) DeepCopyInto(out *VirtualMachineInstanceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachineInstance, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceList. +func (in *VirtualMachineInstanceList) DeepCopy() *VirtualMachineInstanceList { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceMigration) DeepCopyInto(out *VirtualMachineInstanceMigration) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceMigration. +func (in *VirtualMachineInstanceMigration) DeepCopy() *VirtualMachineInstanceMigration { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceMigration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceMigration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceMigrationCondition) DeepCopyInto(out *VirtualMachineInstanceMigrationCondition) { + *out = *in + in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceMigrationCondition. +func (in *VirtualMachineInstanceMigrationCondition) DeepCopy() *VirtualMachineInstanceMigrationCondition { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceMigrationCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceMigrationList) DeepCopyInto(out *VirtualMachineInstanceMigrationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachineInstanceMigration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceMigrationList. +func (in *VirtualMachineInstanceMigrationList) DeepCopy() *VirtualMachineInstanceMigrationList { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceMigrationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceMigrationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceMigrationSpec) DeepCopyInto(out *VirtualMachineInstanceMigrationSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceMigrationSpec. +func (in *VirtualMachineInstanceMigrationSpec) DeepCopy() *VirtualMachineInstanceMigrationSpec { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceMigrationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceMigrationState) DeepCopyInto(out *VirtualMachineInstanceMigrationState) { + *out = *in + if in.StartTimestamp != nil { + in, out := &in.StartTimestamp, &out.StartTimestamp + *out = (*in).DeepCopy() + } + if in.EndTimestamp != nil { + in, out := &in.EndTimestamp, &out.EndTimestamp + *out = (*in).DeepCopy() + } + if in.TargetDirectMigrationNodePorts != nil { + in, out := &in.TargetDirectMigrationNodePorts, &out.TargetDirectMigrationNodePorts + *out = make(map[string]int, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MigrationPolicyName != nil { + in, out := &in.MigrationPolicyName, &out.MigrationPolicyName + *out = new(string) + **out = **in + } + if in.MigrationConfiguration != nil { + in, out := &in.MigrationConfiguration, &out.MigrationConfiguration + *out = new(MigrationConfiguration) + (*in).DeepCopyInto(*out) + } + if in.TargetCPUSet != nil { + in, out := &in.TargetCPUSet, &out.TargetCPUSet + *out = make([]int, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceMigrationState. +func (in *VirtualMachineInstanceMigrationState) DeepCopy() *VirtualMachineInstanceMigrationState { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceMigrationState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceMigrationStatus) DeepCopyInto(out *VirtualMachineInstanceMigrationStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualMachineInstanceMigrationCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceMigrationStatus. +func (in *VirtualMachineInstanceMigrationStatus) DeepCopy() *VirtualMachineInstanceMigrationStatus { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceMigrationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceNetworkInterface) DeepCopyInto(out *VirtualMachineInstanceNetworkInterface) { + *out = *in + if in.IPs != nil { + in, out := &in.IPs, &out.IPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceNetworkInterface. +func (in *VirtualMachineInstanceNetworkInterface) DeepCopy() *VirtualMachineInstanceNetworkInterface { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceNetworkInterface) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstancePhaseTransitionTimestamp) DeepCopyInto(out *VirtualMachineInstancePhaseTransitionTimestamp) { + *out = *in + in.PhaseTransitionTimestamp.DeepCopyInto(&out.PhaseTransitionTimestamp) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstancePhaseTransitionTimestamp. +func (in *VirtualMachineInstancePhaseTransitionTimestamp) DeepCopy() *VirtualMachineInstancePhaseTransitionTimestamp { + if in == nil { + return nil + } + out := new(VirtualMachineInstancePhaseTransitionTimestamp) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstancePreset) DeepCopyInto(out *VirtualMachineInstancePreset) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstancePreset. +func (in *VirtualMachineInstancePreset) DeepCopy() *VirtualMachineInstancePreset { + if in == nil { + return nil + } + out := new(VirtualMachineInstancePreset) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstancePreset) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstancePresetList) DeepCopyInto(out *VirtualMachineInstancePresetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachineInstancePreset, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstancePresetList. +func (in *VirtualMachineInstancePresetList) DeepCopy() *VirtualMachineInstancePresetList { + if in == nil { + return nil + } + out := new(VirtualMachineInstancePresetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstancePresetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstancePresetSpec) DeepCopyInto(out *VirtualMachineInstancePresetSpec) { + *out = *in + in.Selector.DeepCopyInto(&out.Selector) + if in.Domain != nil { + in, out := &in.Domain, &out.Domain + *out = new(DomainSpec) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstancePresetSpec. +func (in *VirtualMachineInstancePresetSpec) DeepCopy() *VirtualMachineInstancePresetSpec { + if in == nil { + return nil + } + out := new(VirtualMachineInstancePresetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceReplicaSet) DeepCopyInto(out *VirtualMachineInstanceReplicaSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceReplicaSet. +func (in *VirtualMachineInstanceReplicaSet) DeepCopy() *VirtualMachineInstanceReplicaSet { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceReplicaSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceReplicaSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceReplicaSetCondition) DeepCopyInto(out *VirtualMachineInstanceReplicaSetCondition) { + *out = *in + in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceReplicaSetCondition. +func (in *VirtualMachineInstanceReplicaSetCondition) DeepCopy() *VirtualMachineInstanceReplicaSetCondition { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceReplicaSetCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceReplicaSetList) DeepCopyInto(out *VirtualMachineInstanceReplicaSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachineInstanceReplicaSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceReplicaSetList. +func (in *VirtualMachineInstanceReplicaSetList) DeepCopy() *VirtualMachineInstanceReplicaSetList { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceReplicaSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineInstanceReplicaSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceReplicaSetSpec) DeepCopyInto(out *VirtualMachineInstanceReplicaSetSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(VirtualMachineInstanceTemplateSpec) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceReplicaSetSpec. +func (in *VirtualMachineInstanceReplicaSetSpec) DeepCopy() *VirtualMachineInstanceReplicaSetSpec { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceReplicaSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceReplicaSetStatus) DeepCopyInto(out *VirtualMachineInstanceReplicaSetStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualMachineInstanceReplicaSetCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceReplicaSetStatus. +func (in *VirtualMachineInstanceReplicaSetStatus) DeepCopy() *VirtualMachineInstanceReplicaSetStatus { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceReplicaSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceSpec) DeepCopyInto(out *VirtualMachineInstanceSpec) { + *out = *in + in.Domain.DeepCopyInto(&out.Domain) + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(corev1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EvictionStrategy != nil { + in, out := &in.EvictionStrategy, &out.EvictionStrategy + *out = new(EvictionStrategy) + **out = **in + } + if in.StartStrategy != nil { + in, out := &in.StartStrategy, &out.StartStrategy + *out = new(StartStrategy) + **out = **in + } + if in.TerminationGracePeriodSeconds != nil { + in, out := &in.TerminationGracePeriodSeconds, &out.TerminationGracePeriodSeconds + *out = new(int64) + **out = **in + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LivenessProbe != nil { + in, out := &in.LivenessProbe, &out.LivenessProbe + *out = new(Probe) + (*in).DeepCopyInto(*out) + } + if in.ReadinessProbe != nil { + in, out := &in.ReadinessProbe, &out.ReadinessProbe + *out = new(Probe) + (*in).DeepCopyInto(*out) + } + if in.Networks != nil { + in, out := &in.Networks, &out.Networks + *out = make([]Network, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DNSConfig != nil { + in, out := &in.DNSConfig, &out.DNSConfig + *out = new(corev1.PodDNSConfig) + (*in).DeepCopyInto(*out) + } + if in.AccessCredentials != nil { + in, out := &in.AccessCredentials, &out.AccessCredentials + *out = make([]AccessCredential, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceSpec. +func (in *VirtualMachineInstanceSpec) DeepCopy() *VirtualMachineInstanceSpec { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceStatus) DeepCopyInto(out *VirtualMachineInstanceStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualMachineInstanceCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.PhaseTransitionTimestamps != nil { + in, out := &in.PhaseTransitionTimestamps, &out.PhaseTransitionTimestamps + *out = make([]VirtualMachineInstancePhaseTransitionTimestamp, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Interfaces != nil { + in, out := &in.Interfaces, &out.Interfaces + *out = make([]VirtualMachineInstanceNetworkInterface, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.GuestOSInfo = in.GuestOSInfo + if in.MigrationState != nil { + in, out := &in.MigrationState, &out.MigrationState + *out = new(VirtualMachineInstanceMigrationState) + (*in).DeepCopyInto(*out) + } + if in.QOSClass != nil { + in, out := &in.QOSClass, &out.QOSClass + *out = new(corev1.PodQOSClass) + **out = **in + } + if in.ActivePods != nil { + in, out := &in.ActivePods, &out.ActivePods + *out = make(map[types.UID]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.VolumeStatus != nil { + in, out := &in.VolumeStatus, &out.VolumeStatus + *out = make([]VolumeStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.TopologyHints != nil { + in, out := &in.TopologyHints, &out.TopologyHints + *out = new(TopologyHints) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceStatus. +func (in *VirtualMachineInstanceStatus) DeepCopy() *VirtualMachineInstanceStatus { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineInstanceTemplateSpec) DeepCopyInto(out *VirtualMachineInstanceTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineInstanceTemplateSpec. +func (in *VirtualMachineInstanceTemplateSpec) DeepCopy() *VirtualMachineInstanceTemplateSpec { + if in == nil { + return nil + } + out := new(VirtualMachineInstanceTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineList) DeepCopyInto(out *VirtualMachineList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualMachine, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineList. +func (in *VirtualMachineList) DeepCopy() *VirtualMachineList { + if in == nil { + return nil + } + out := new(VirtualMachineList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualMachineList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineMemoryDumpRequest) DeepCopyInto(out *VirtualMachineMemoryDumpRequest) { + *out = *in + if in.StartTimestamp != nil { + in, out := &in.StartTimestamp, &out.StartTimestamp + *out = (*in).DeepCopy() + } + if in.EndTimestamp != nil { + in, out := &in.EndTimestamp, &out.EndTimestamp + *out = (*in).DeepCopy() + } + if in.FileName != nil { + in, out := &in.FileName, &out.FileName + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineMemoryDumpRequest. +func (in *VirtualMachineMemoryDumpRequest) DeepCopy() *VirtualMachineMemoryDumpRequest { + if in == nil { + return nil + } + out := new(VirtualMachineMemoryDumpRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineSpec) DeepCopyInto(out *VirtualMachineSpec) { + *out = *in + if in.Running != nil { + in, out := &in.Running, &out.Running + *out = new(bool) + **out = **in + } + if in.RunStrategy != nil { + in, out := &in.RunStrategy, &out.RunStrategy + *out = new(VirtualMachineRunStrategy) + **out = **in + } + if in.Flavor != nil { + in, out := &in.Flavor, &out.Flavor + *out = new(FlavorMatcher) + **out = **in + } + if in.Preference != nil { + in, out := &in.Preference, &out.Preference + *out = new(PreferenceMatcher) + **out = **in + } + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(VirtualMachineInstanceTemplateSpec) + (*in).DeepCopyInto(*out) + } + if in.DataVolumeTemplates != nil { + in, out := &in.DataVolumeTemplates, &out.DataVolumeTemplates + *out = make([]DataVolumeTemplateSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineSpec. +func (in *VirtualMachineSpec) DeepCopy() *VirtualMachineSpec { + if in == nil { + return nil + } + out := new(VirtualMachineSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineStartFailure) DeepCopyInto(out *VirtualMachineStartFailure) { + *out = *in + if in.RetryAfterTimestamp != nil { + in, out := &in.RetryAfterTimestamp, &out.RetryAfterTimestamp + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineStartFailure. +func (in *VirtualMachineStartFailure) DeepCopy() *VirtualMachineStartFailure { + if in == nil { + return nil + } + out := new(VirtualMachineStartFailure) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineStateChangeRequest) DeepCopyInto(out *VirtualMachineStateChangeRequest) { + *out = *in + if in.Data != nil { + in, out := &in.Data, &out.Data + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.UID != nil { + in, out := &in.UID, &out.UID + *out = new(types.UID) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineStateChangeRequest. +func (in *VirtualMachineStateChangeRequest) DeepCopy() *VirtualMachineStateChangeRequest { + if in == nil { + return nil + } + out := new(VirtualMachineStateChangeRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineStatus) DeepCopyInto(out *VirtualMachineStatus) { + *out = *in + if in.SnapshotInProgress != nil { + in, out := &in.SnapshotInProgress, &out.SnapshotInProgress + *out = new(string) + **out = **in + } + if in.RestoreInProgress != nil { + in, out := &in.RestoreInProgress, &out.RestoreInProgress + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualMachineCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.StateChangeRequests != nil { + in, out := &in.StateChangeRequests, &out.StateChangeRequests + *out = make([]VirtualMachineStateChangeRequest, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.VolumeRequests != nil { + in, out := &in.VolumeRequests, &out.VolumeRequests + *out = make([]VirtualMachineVolumeRequest, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.VolumeSnapshotStatuses != nil { + in, out := &in.VolumeSnapshotStatuses, &out.VolumeSnapshotStatuses + *out = make([]VolumeSnapshotStatus, len(*in)) + copy(*out, *in) + } + if in.StartFailure != nil { + in, out := &in.StartFailure, &out.StartFailure + *out = new(VirtualMachineStartFailure) + (*in).DeepCopyInto(*out) + } + if in.MemoryDumpRequest != nil { + in, out := &in.MemoryDumpRequest, &out.MemoryDumpRequest + *out = new(VirtualMachineMemoryDumpRequest) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineStatus. +func (in *VirtualMachineStatus) DeepCopy() *VirtualMachineStatus { + if in == nil { + return nil + } + out := new(VirtualMachineStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineVolumeRequest) DeepCopyInto(out *VirtualMachineVolumeRequest) { + *out = *in + if in.AddVolumeOptions != nil { + in, out := &in.AddVolumeOptions, &out.AddVolumeOptions + *out = new(AddVolumeOptions) + (*in).DeepCopyInto(*out) + } + if in.RemoveVolumeOptions != nil { + in, out := &in.RemoveVolumeOptions, &out.RemoveVolumeOptions + *out = new(RemoveVolumeOptions) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineVolumeRequest. +func (in *VirtualMachineVolumeRequest) DeepCopy() *VirtualMachineVolumeRequest { + if in == nil { + return nil + } + out := new(VirtualMachineVolumeRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Volume) DeepCopyInto(out *Volume) { + *out = *in + in.VolumeSource.DeepCopyInto(&out.VolumeSource) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Volume. +func (in *Volume) DeepCopy() *Volume { + if in == nil { + return nil + } + out := new(Volume) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotStatus) DeepCopyInto(out *VolumeSnapshotStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotStatus. +func (in *VolumeSnapshotStatus) DeepCopy() *VolumeSnapshotStatus { + if in == nil { + return nil + } + out := new(VolumeSnapshotStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSource) DeepCopyInto(out *VolumeSource) { + *out = *in + if in.HostDisk != nil { + in, out := &in.HostDisk, &out.HostDisk + *out = new(HostDisk) + (*in).DeepCopyInto(*out) + } + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(PersistentVolumeClaimVolumeSource) + **out = **in + } + if in.CloudInitNoCloud != nil { + in, out := &in.CloudInitNoCloud, &out.CloudInitNoCloud + *out = new(CloudInitNoCloudSource) + (*in).DeepCopyInto(*out) + } + if in.CloudInitConfigDrive != nil { + in, out := &in.CloudInitConfigDrive, &out.CloudInitConfigDrive + *out = new(CloudInitConfigDriveSource) + (*in).DeepCopyInto(*out) + } + if in.Sysprep != nil { + in, out := &in.Sysprep, &out.Sysprep + *out = new(SysprepSource) + (*in).DeepCopyInto(*out) + } + if in.ContainerDisk != nil { + in, out := &in.ContainerDisk, &out.ContainerDisk + *out = new(ContainerDiskSource) + **out = **in + } + if in.Ephemeral != nil { + in, out := &in.Ephemeral, &out.Ephemeral + *out = new(EphemeralVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.EmptyDisk != nil { + in, out := &in.EmptyDisk, &out.EmptyDisk + *out = new(EmptyDiskSource) + (*in).DeepCopyInto(*out) + } + if in.DataVolume != nil { + in, out := &in.DataVolume, &out.DataVolume + *out = new(DataVolumeSource) + **out = **in + } + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap + *out = new(ConfigMapVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.Secret != nil { + in, out := &in.Secret, &out.Secret + *out = new(SecretVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.DownwardAPI != nil { + in, out := &in.DownwardAPI, &out.DownwardAPI + *out = new(DownwardAPIVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.ServiceAccount != nil { + in, out := &in.ServiceAccount, &out.ServiceAccount + *out = new(ServiceAccountVolumeSource) + **out = **in + } + if in.DownwardMetrics != nil { + in, out := &in.DownwardMetrics, &out.DownwardMetrics + *out = new(DownwardMetricsVolumeSource) + **out = **in + } + if in.MemoryDump != nil { + in, out := &in.MemoryDump, &out.MemoryDump + *out = new(MemoryDumpVolumeSource) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSource. +func (in *VolumeSource) DeepCopy() *VolumeSource { + if in == nil { + return nil + } + out := new(VolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeStatus) DeepCopyInto(out *VolumeStatus) { + *out = *in + if in.PersistentVolumeClaimInfo != nil { + in, out := &in.PersistentVolumeClaimInfo, &out.PersistentVolumeClaimInfo + *out = new(PersistentVolumeClaimInfo) + (*in).DeepCopyInto(*out) + } + if in.HotplugVolume != nil { + in, out := &in.HotplugVolume, &out.HotplugVolume + *out = new(HotplugVolumeStatus) + **out = **in + } + if in.MemoryDumpVolume != nil { + in, out := &in.MemoryDumpVolume, &out.MemoryDumpVolume + *out = new(DomainMemoryDumpInfo) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeStatus. +func (in *VolumeStatus) DeepCopy() *VolumeStatus { + if in == nil { + return nil + } + out := new(VolumeStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Watchdog) DeepCopyInto(out *Watchdog) { + *out = *in + in.WatchdogDevice.DeepCopyInto(&out.WatchdogDevice) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Watchdog. +func (in *Watchdog) DeepCopy() *Watchdog { + if in == nil { + return nil + } + out := new(Watchdog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WatchdogDevice) DeepCopyInto(out *WatchdogDevice) { + *out = *in + if in.I6300ESB != nil { + in, out := &in.I6300ESB, &out.I6300ESB + *out = new(I6300ESBWatchdog) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchdogDevice. +func (in *WatchdogDevice) DeepCopy() *WatchdogDevice { + if in == nil { + return nil + } + out := new(WatchdogDevice) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/kubevirt.io/api/core/v1/defaults.go b/vendor/kubevirt.io/api/core/v1/defaults.go new file mode 100644 index 00000000..cc0c4e15 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/defaults.go @@ -0,0 +1,241 @@ +package v1 + +import ( + "github.com/pborman/uuid" + "k8s.io/apimachinery/pkg/types" +) + +var _true = t(true) +var _false = t(false) + +func SetDefaults_HPETTimer(obj *HPETTimer) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_PITTimer(obj *PITTimer) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_KVMTimer(obj *KVMTimer) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_HypervTimer(obj *HypervTimer) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_RTCTimer(obj *RTCTimer) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_FeatureState(obj *FeatureState) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_SyNICTimer(obj *SyNICTimer) { + if obj.Enabled == nil { + obj.Enabled = _true + } + + if obj.Direct != nil && obj.Direct.Enabled == nil { + obj.Direct.Enabled = _true + } +} + +func SetDefaults_FeatureAPIC(obj *FeatureAPIC) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_FeatureVendorID(obj *FeatureVendorID) { + if obj.Enabled == nil { + obj.Enabled = _true + } +} + +func SetDefaults_DiskDevice(obj *DiskDevice) { + if obj.Disk == nil && + obj.CDRom == nil && + obj.LUN == nil { + obj.Disk = &DiskTarget{} + } +} + +func SetDefaults_Watchdog(obj *Watchdog) { + if obj.I6300ESB == nil { + obj.I6300ESB = &I6300ESBWatchdog{} + } +} + +func SetDefaults_CDRomTarget(obj *CDRomTarget) { + if obj.ReadOnly == nil { + obj.ReadOnly = _true + } + if obj.Tray == "" { + obj.Tray = TrayStateClosed + } +} + +func SetDefaults_FeatureSpinlocks(obj *FeatureSpinlocks) { + if obj.Enabled == nil { + obj.Enabled = _true + } + if *obj.Enabled == *_true && obj.Retries == nil { + obj.Retries = ui32(4096) + } +} + +func SetDefaults_I6300ESBWatchdog(obj *I6300ESBWatchdog) { + if obj.Action == "" { + obj.Action = WatchdogActionReset + } +} + +func SetDefaults_Firmware(obj *Firmware) { + if obj.UUID == "" { + obj.UUID = types.UID(uuid.NewRandom().String()) + } +} + +func SetDefaults_VirtualMachineInstance(obj *VirtualMachineInstance) { + if obj.Spec.Domain.Firmware == nil { + obj.Spec.Domain.Firmware = &Firmware{} + } + + if obj.Spec.Domain.Features == nil { + obj.Spec.Domain.Features = &Features{} + } + + setDefaults_Disk(obj) + SetDefaults_Probe(obj.Spec.ReadinessProbe) + SetDefaults_Probe(obj.Spec.LivenessProbe) +} + +func setDefaults_Disk(obj *VirtualMachineInstance) { + // Setting SATA as the default bus since it is typically supported out of the box by + // guest operating systems (we support only q35 and therefore IDE is not supported) + // TODO: consider making this OS-specific (VIRTIO for linux, SATA for others) + bus := DiskBusSATA + + for i := range obj.Spec.Domain.Devices.Disks { + disk := &obj.Spec.Domain.Devices.Disks[i].DiskDevice + + SetDefaults_DiskDevice(disk) + + if disk.Disk != nil && disk.Disk.Bus == "" { + disk.Disk.Bus = bus + } + if disk.CDRom != nil && disk.CDRom.Bus == "" { + disk.CDRom.Bus = bus + } + if disk.LUN != nil && disk.LUN.Bus == "" { + disk.LUN.Bus = bus + } + } +} + +func SetDefaults_Probe(probe *Probe) { + if probe == nil { + return + } + + if probe.TimeoutSeconds < 1 { + probe.TimeoutSeconds = 1 + } + + if probe.PeriodSeconds < 1 { + probe.PeriodSeconds = 10 + } + + if probe.SuccessThreshold < 1 { + probe.SuccessThreshold = 1 + } + + if probe.FailureThreshold < 1 { + probe.FailureThreshold = 3 + } +} + +func SetDefaults_NetworkInterface(obj *VirtualMachineInstance) { + autoAttach := obj.Spec.Domain.Devices.AutoattachPodInterface + if autoAttach != nil && *autoAttach == false { + return + } + + // Override only when nothing is specified + if len(obj.Spec.Networks) == 0 { + obj.Spec.Domain.Devices.Interfaces = []Interface{*DefaultBridgeNetworkInterface()} + obj.Spec.Networks = []Network{*DefaultPodNetwork()} + } +} + +func DefaultBridgeNetworkInterface() *Interface { + iface := &Interface{ + Name: "default", + InterfaceBindingMethod: InterfaceBindingMethod{ + Bridge: &InterfaceBridge{}, + }, + } + return iface +} + +func DefaultSlirpNetworkInterface() *Interface { + iface := &Interface{ + Name: "default", + InterfaceBindingMethod: InterfaceBindingMethod{ + Slirp: &InterfaceSlirp{}, + }, + } + return iface +} + +func DefaultMasqueradeNetworkInterface() *Interface { + iface := &Interface{ + Name: "default", + InterfaceBindingMethod: InterfaceBindingMethod{ + Masquerade: &InterfaceMasquerade{}, + }, + } + return iface +} + +func DefaultMacvtapNetworkInterface(ifaceName string) *Interface { + iface := &Interface{ + Name: ifaceName, + InterfaceBindingMethod: InterfaceBindingMethod{ + Macvtap: &InterfaceMacvtap{}, + }, + } + return iface +} + +func DefaultPodNetwork() *Network { + defaultNet := &Network{ + Name: "default", + NetworkSource: NetworkSource{ + Pod: &PodNetwork{}, + }, + } + return defaultNet +} + +func t(v bool) *bool { + return &v +} + +func ui32(v uint32) *uint32 { + return &v +} diff --git a/vendor/kubevirt.io/api/core/v1/doc.go b/vendor/kubevirt.io/api/core/v1/doc.go new file mode 100644 index 00000000..d434314c --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/doc.go @@ -0,0 +1,8 @@ +// +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta + +// +groupName=kubevirt.io +// +versionName=v1alpha3 +// +k8s:openapi-gen=true +// Package v1 is the v1 version of the API. +package v1 diff --git a/vendor/kubevirt.io/api/core/v1/register.go b/vendor/kubevirt.io/api/core/v1/register.go new file mode 100644 index 00000000..2bc8efc4 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/register.go @@ -0,0 +1,121 @@ +/* + * This file is part of the KubeVirt project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2019 Red Hat, Inc. + * + */ +package v1 + +import ( + extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "kubevirt.io/api/core" +) + +const SubresourceGroupName = "subresources.kubevirt.io" +const KubeVirtClientGoSchemeRegistrationVersionEnvVar = "KUBEVIRT_CLIENT_GO_SCHEME_REGISTRATION_VERSION" + +var ( + ApiLatestVersion = "v1" + ApiSupportedWebhookVersions = []string{"v1alpha3", "v1"} + ApiStorageVersion = "v1alpha3" + ApiSupportedVersions = []extv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: false, + }, + { + Name: "v1alpha3", + Served: true, + Storage: true, + }, + } +) + +var ( + // GroupVersion is the latest group version for the KubeVirt api + GroupVersion = schema.GroupVersion{Group: core.GroupName, Version: ApiLatestVersion} + SchemeGroupVersion = schema.GroupVersion{Group: core.GroupName, Version: ApiLatestVersion} + + // StorageGroupVersion is the group version our api is persistented internally as + StorageGroupVersion = schema.GroupVersion{Group: core.GroupName, Version: ApiStorageVersion} + + // GroupVersions is group version list used to register these objects + // The preferred group version is the first item in the list. + GroupVersions = []schema.GroupVersion{{Group: core.GroupName, Version: "v1"}, {Group: core.GroupName, Version: "v1alpha3"}} + + // SubresourceGroupVersions is group version list used to register these objects + // The preferred group version is the first item in the list. + SubresourceGroupVersions = []schema.GroupVersion{{Group: SubresourceGroupName, Version: ApiLatestVersion}, {Group: SubresourceGroupName, Version: ApiStorageVersion}} + + // SubresourceStorageGroupVersion is the group version our api is persistented internally as + SubresourceStorageGroupVersion = schema.GroupVersion{Group: SubresourceGroupName, Version: ApiStorageVersion} +) + +var ( + // GroupVersionKind + VirtualMachineInstanceGroupVersionKind = schema.GroupVersionKind{Group: core.GroupName, Version: GroupVersion.Version, Kind: "VirtualMachineInstance"} + VirtualMachineInstanceReplicaSetGroupVersionKind = schema.GroupVersionKind{Group: core.GroupName, Version: GroupVersion.Version, Kind: "VirtualMachineInstanceReplicaSet"} + VirtualMachineInstancePresetGroupVersionKind = schema.GroupVersionKind{Group: core.GroupName, Version: GroupVersion.Version, Kind: "VirtualMachineInstancePreset"} + VirtualMachineGroupVersionKind = schema.GroupVersionKind{Group: core.GroupName, Version: GroupVersion.Version, Kind: "VirtualMachine"} + VirtualMachineInstanceMigrationGroupVersionKind = schema.GroupVersionKind{Group: core.GroupName, Version: GroupVersion.Version, Kind: "VirtualMachineInstanceMigration"} + KubeVirtGroupVersionKind = schema.GroupVersionKind{Group: core.GroupName, Version: GroupVersion.Version, Kind: "KubeVirt"} +) + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(AddKnownTypesGenerator([]schema.GroupVersion{GroupVersion})) + AddToScheme = SchemeBuilder.AddToScheme +) + +func AddKnownTypesGenerator(groupVersions []schema.GroupVersion) func(scheme *runtime.Scheme) error { + + // Adds the list of known types to api.Scheme. + return func(scheme *runtime.Scheme) error { + + for _, groupVersion := range groupVersions { + scheme.AddKnownTypes(groupVersion, + &VirtualMachineInstance{}, + &VirtualMachineInstanceList{}, + &VirtualMachineInstanceReplicaSet{}, + &VirtualMachineInstanceReplicaSetList{}, + &VirtualMachineInstancePreset{}, + &VirtualMachineInstancePresetList{}, + &VirtualMachineInstanceMigration{}, + &VirtualMachineInstanceMigrationList{}, + &VirtualMachine{}, + &VirtualMachineList{}, + &KubeVirt{}, + &KubeVirtList{}, + ) + metav1.AddToGroupVersion(scheme, groupVersion) + } + + return nil + } +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return GroupVersion.WithResource(resource).GroupResource() +} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} diff --git a/vendor/kubevirt.io/api/core/v1/sanitizers.go b/vendor/kubevirt.io/api/core/v1/sanitizers.go new file mode 100644 index 00000000..5df10477 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/sanitizers.go @@ -0,0 +1,45 @@ +/* + * This file is part of the KubeVirt project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2022 Red Hat, Inc. + * + */ + +package v1 + +import ( + "fmt" + + netutils "k8s.io/utils/net" +) + +func sanitizeIP(address string) (string, error) { + sanitizedAddress := netutils.ParseIPSloppy(address) + if sanitizedAddress == nil { + return "", fmt.Errorf("not a valid IP address") + } + + return sanitizedAddress.String(), nil +} + +func sanitizeCIDR(cidr string) (string, error) { + ip, net, err := netutils.ParseCIDRSloppy(cidr) + if err != nil { + return "", err + } + + netMaskSize, _ := net.Mask.Size() + return fmt.Sprintf("%s/%d", ip.String(), netMaskSize), nil +} diff --git a/vendor/kubevirt.io/api/core/v1/schema.go b/vendor/kubevirt.io/api/core/v1/schema.go new file mode 100644 index 00000000..2db8e48d --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/schema.go @@ -0,0 +1,1407 @@ +/* + * This file is part of the KubeVirt project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2017, 2018 Red Hat, Inc. + * + */ + +package v1 + +import ( + "encoding/json" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" +) + +type IOThreadsPolicy string + +const ( + IOThreadsPolicyShared IOThreadsPolicy = "shared" + IOThreadsPolicyAuto IOThreadsPolicy = "auto" + CPUModeHostPassthrough = "host-passthrough" + CPUModeHostModel = "host-model" + DefaultCPUModel = CPUModeHostModel +) + +/* + ATTENTION: Rerun code generators when comments on structs or fields are modified. +*/ + +// Represents a disk created on the cluster level +type HostDisk struct { + // The path to HostDisk image located on the cluster + Path string `json:"path"` + // Contains information if disk.img exists or should be created + // allowed options are 'Disk' and 'DiskOrCreate' + Type HostDiskType `json:"type"` + // Capacity of the sparse disk + // +optional + Capacity resource.Quantity `json:"capacity,omitempty"` + // Shared indicate whether the path is shared between nodes + Shared *bool `json:"shared,omitempty"` +} + +// ConfigMapVolumeSource adapts a ConfigMap into a volume. +// More info: https://kubernetes.io/docs/concepts/storage/volumes/#configmap +type ConfigMapVolumeSource struct { + v1.LocalObjectReference `json:",inline"` + // Specify whether the ConfigMap or it's keys must be defined + // +optional + Optional *bool `json:"optional,omitempty"` + // The volume label of the resulting disk inside the VMI. + // Different bootstrapping mechanisms require different values. + // Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). + // +optional + VolumeLabel string `json:"volumeLabel,omitempty"` +} + +// SecretVolumeSource adapts a Secret into a volume. +type SecretVolumeSource struct { + // Name of the secret in the pod's namespace to use. + // More info: https://kubernetes.io/docs/concepts/storage/volumes#secret + // +optional + SecretName string `json:"secretName,omitempty"` + // Specify whether the Secret or it's keys must be defined + // +optional + Optional *bool `json:"optional,omitempty"` + // The volume label of the resulting disk inside the VMI. + // Different bootstrapping mechanisms require different values. + // Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). + // +optional + VolumeLabel string `json:"volumeLabel,omitempty"` +} + +// DownwardAPIVolumeSource represents a volume containing downward API info. +type DownwardAPIVolumeSource struct { + // Fields is a list of downward API volume file + // +optional + Fields []v1.DownwardAPIVolumeFile `json:"fields,omitempty"` + // The volume label of the resulting disk inside the VMI. + // Different bootstrapping mechanisms require different values. + // Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). + // +optional + VolumeLabel string `json:"volumeLabel,omitempty"` +} + +// ServiceAccountVolumeSource adapts a ServiceAccount into a volume. +type ServiceAccountVolumeSource struct { + // Name of the service account in the pod's namespace to use. + // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ServiceAccountName string `json:"serviceAccountName,omitempty"` +} + +// DownwardMetricsVolumeSource adds a very small disk to VMIs which contains a limited view of host and guest +// metrics. The disk content is compatible with vhostmd (https://github.com/vhostmd/vhostmd) and vm-dump-metrics. +type DownwardMetricsVolumeSource struct { +} + +// Represents a Sysprep volume source. +type SysprepSource struct { + // Secret references a k8s Secret that contains Sysprep answer file named autounattend.xml that should be attached as disk of CDROM type. + // + optional + Secret *v1.LocalObjectReference `json:"secret,omitempty"` + // ConfigMap references a ConfigMap that contains Sysprep answer file named autounattend.xml that should be attached as disk of CDROM type. + // + optional + ConfigMap *v1.LocalObjectReference `json:"configMap,omitempty"` +} + +// Represents a cloud-init nocloud user data source. +// More info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html +type CloudInitNoCloudSource struct { + // UserDataSecretRef references a k8s secret that contains NoCloud userdata. + // + optional + UserDataSecretRef *v1.LocalObjectReference `json:"secretRef,omitempty"` + // UserDataBase64 contains NoCloud cloud-init userdata as a base64 encoded string. + // + optional + UserDataBase64 string `json:"userDataBase64,omitempty"` + // UserData contains NoCloud inline cloud-init userdata. + // + optional + UserData string `json:"userData,omitempty"` + // NetworkDataSecretRef references a k8s secret that contains NoCloud networkdata. + // + optional + NetworkDataSecretRef *v1.LocalObjectReference `json:"networkDataSecretRef,omitempty"` + // NetworkDataBase64 contains NoCloud cloud-init networkdata as a base64 encoded string. + // + optional + NetworkDataBase64 string `json:"networkDataBase64,omitempty"` + // NetworkData contains NoCloud inline cloud-init networkdata. + // + optional + NetworkData string `json:"networkData,omitempty"` +} + +// Represents a cloud-init config drive user data source. +// More info: https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html +type CloudInitConfigDriveSource struct { + // UserDataSecretRef references a k8s secret that contains config drive userdata. + // + optional + UserDataSecretRef *v1.LocalObjectReference `json:"secretRef,omitempty"` + // UserDataBase64 contains config drive cloud-init userdata as a base64 encoded string. + // + optional + UserDataBase64 string `json:"userDataBase64,omitempty"` + // UserData contains config drive inline cloud-init userdata. + // + optional + UserData string `json:"userData,omitempty"` + // NetworkDataSecretRef references a k8s secret that contains config drive networkdata. + // + optional + NetworkDataSecretRef *v1.LocalObjectReference `json:"networkDataSecretRef,omitempty"` + // NetworkDataBase64 contains config drive cloud-init networkdata as a base64 encoded string. + // + optional + NetworkDataBase64 string `json:"networkDataBase64,omitempty"` + // NetworkData contains config drive inline cloud-init networkdata. + // + optional + NetworkData string `json:"networkData,omitempty"` +} + +type DomainSpec struct { + // Resources describes the Compute Resources required by this vmi. + Resources ResourceRequirements `json:"resources,omitempty"` + // CPU allow specified the detailed CPU topology inside the vmi. + // +optional + CPU *CPU `json:"cpu,omitempty"` + // Memory allow specifying the VMI memory features. + // +optional + Memory *Memory `json:"memory,omitempty"` + // Machine type. + // +optional + Machine *Machine `json:"machine,omitempty"` + // Firmware. + // +optional + Firmware *Firmware `json:"firmware,omitempty"` + // Clock sets the clock and timers of the vmi. + // +optional + Clock *Clock `json:"clock,omitempty"` + // Features like acpi, apic, hyperv, smm. + // +optional + Features *Features `json:"features,omitempty"` + // Devices allows adding disks, network interfaces, and others + Devices Devices `json:"devices"` + // Controls whether or not disks will share IOThreads. + // Omitting IOThreadsPolicy disables use of IOThreads. + // One of: shared, auto + // +optional + IOThreadsPolicy *IOThreadsPolicy `json:"ioThreadsPolicy,omitempty"` + // Chassis specifies the chassis info passed to the domain. + // +optional + Chassis *Chassis `json:"chassis,omitempty"` + // Launch Security setting of the vmi. + // +optional + LaunchSecurity *LaunchSecurity `json:"launchSecurity,omitempty"` +} + +// Chassis specifies the chassis info passed to the domain. +type Chassis struct { + Manufacturer string `json:"manufacturer,omitempty"` + Version string `json:"version,omitempty"` + Serial string `json:"serial,omitempty"` + Asset string `json:"asset,omitempty"` + Sku string `json:"sku,omitempty"` +} + +// Represents the firmware blob used to assist in the domain creation process. +// Used for setting the QEMU BIOS file path for the libvirt domain. +type Bootloader struct { + // If set (default), BIOS will be used. + // +optional + BIOS *BIOS `json:"bios,omitempty"` + // If set, EFI will be used instead of BIOS. + // +optional + EFI *EFI `json:"efi,omitempty"` +} + +// If set (default), BIOS will be used. +type BIOS struct { + // If set, the BIOS output will be transmitted over serial + // +optional + UseSerial *bool `json:"useSerial,omitempty"` +} + +// If set, EFI will be used instead of BIOS. +type EFI struct { + // If set, SecureBoot will be enabled and the OVMF roms will be swapped for + // SecureBoot-enabled ones. + // Requires SMM to be enabled. + // Defaults to true + // +optional + SecureBoot *bool `json:"secureBoot,omitempty"` +} + +// If set, the VM will be booted from the defined kernel / initrd. +type KernelBootContainer struct { + // Image that contains initrd / kernel files. + Image string `json:"image"` + // ImagePullSecret is the name of the Docker registry secret required to pull the image. The secret must already exist. + //+optional + ImagePullSecret string `json:"imagePullSecret,omitempty"` + // Image pull policy. + // One of Always, Never, IfNotPresent. + // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + // +optional + ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"` + // The fully-qualified path to the kernel image in the host OS + //+optional + KernelPath string `json:"kernelPath,omitempty"` + // the fully-qualified path to the ramdisk image in the host OS + //+optional + InitrdPath string `json:"initrdPath,omitempty"` +} + +// Represents the firmware blob used to assist in the kernel boot process. +// Used for setting the kernel, initrd and command line arguments +type KernelBoot struct { + // Arguments to be passed to the kernel at boot time + KernelArgs string `json:"kernelArgs,omitempty"` + // Container defines the container that containes kernel artifacts + Container *KernelBootContainer `json:"container,omitempty"` +} + +type ResourceRequirements struct { + // Requests is a description of the initial vmi resources. + // Valid resource keys are "memory" and "cpu". + // +optional + Requests v1.ResourceList `json:"requests,omitempty"` + // Limits describes the maximum amount of compute resources allowed. + // Valid resource keys are "memory" and "cpu". + // +optional + Limits v1.ResourceList `json:"limits,omitempty"` + // Don't ask the scheduler to take the guest-management overhead into account. Instead + // put the overhead only into the container's memory limit. This can lead to crashes if + // all memory is in use on a node. Defaults to false. + OvercommitGuestOverhead bool `json:"overcommitGuestOverhead,omitempty"` +} + +// CPU allows specifying the CPU topology. +type CPU struct { + // Cores specifies the number of cores inside the vmi. + // Must be a value greater or equal 1. + Cores uint32 `json:"cores,omitempty"` + // Sockets specifies the number of sockets inside the vmi. + // Must be a value greater or equal 1. + Sockets uint32 `json:"sockets,omitempty"` + // Threads specifies the number of threads inside the vmi. + // Must be a value greater or equal 1. + Threads uint32 `json:"threads,omitempty"` + // Model specifies the CPU model inside the VMI. + // List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map. + // It is possible to specify special cases like "host-passthrough" to get the same CPU as the node + // and "host-model" to get CPU closest to the node one. + // Defaults to host-model. + // +optional + Model string `json:"model,omitempty"` + // Features specifies the CPU features list inside the VMI. + // +optional + Features []CPUFeature `json:"features,omitempty"` + // DedicatedCPUPlacement requests the scheduler to place the VirtualMachineInstance on a node + // with enough dedicated pCPUs and pin the vCPUs to it. + // +optional + DedicatedCPUPlacement bool `json:"dedicatedCpuPlacement,omitempty"` + + // NUMA allows specifying settings for the guest NUMA topology + // +optional + NUMA *NUMA `json:"numa,omitempty"` + + // IsolateEmulatorThread requests one more dedicated pCPU to be allocated for the VMI to place + // the emulator thread on it. + // +optional + IsolateEmulatorThread bool `json:"isolateEmulatorThread,omitempty"` + // Realtime instructs the virt-launcher to tune the VMI for lower latency, optional for real time workloads + // +optional + Realtime *Realtime `json:"realtime,omitempty"` +} + +// Realtime holds the tuning knobs specific for realtime workloads. +type Realtime struct { + // Mask defines the vcpu mask expression that defines which vcpus are used for realtime. Format matches libvirt's expressions. + // Example: "0-3,^1","0,2,3","2-3" + // +optional + Mask string `json:"mask,omitempty"` +} + +// NUMAGuestMappingPassthrough instructs kubevirt to model numa topology which is compatible with the CPU pinning on the guest. +// This will result in a subset of the node numa topology being passed through, ensuring that virtual numa nodes and their memory +// never cross boundaries coming from the node numa mapping. +type NUMAGuestMappingPassthrough struct { +} + +type NUMA struct { + // GuestMappingPassthrough will create an efficient guest topology based on host CPUs exclusively assigned to a pod. + // The created topology ensures that memory and CPUs on the virtual numa nodes never cross boundaries of host numa nodes. + // +opitonal + GuestMappingPassthrough *NUMAGuestMappingPassthrough `json:"guestMappingPassthrough,omitempty"` +} + +// CPUFeature allows specifying a CPU feature. +type CPUFeature struct { + // Name of the CPU feature + Name string `json:"name"` + // Policy is the CPU feature attribute which can have the following attributes: + // force - The virtual CPU will claim the feature is supported regardless of it being supported by host CPU. + // require - Guest creation will fail unless the feature is supported by the host CPU or the hypervisor is able to emulate it. + // optional - The feature will be supported by virtual CPU if and only if it is supported by host CPU. + // disable - The feature will not be supported by virtual CPU. + // forbid - Guest creation will fail if the feature is supported by host CPU. + // Defaults to require + // +optional + Policy string `json:"policy,omitempty"` +} + +// Memory allows specifying the VirtualMachineInstance memory features. +type Memory struct { + // Hugepages allow to use hugepages for the VirtualMachineInstance instead of regular memory. + // +optional + Hugepages *Hugepages `json:"hugepages,omitempty"` + // Guest allows to specifying the amount of memory which is visible inside the Guest OS. + // The Guest must lie between Requests and Limits from the resources section. + // Defaults to the requested memory in the resources section if not specified. + // + optional + Guest *resource.Quantity `json:"guest,omitempty"` +} + +// Hugepages allow to use hugepages for the VirtualMachineInstance instead of regular memory. +type Hugepages struct { + // PageSize specifies the hugepage size, for x86_64 architecture valid values are 1Gi and 2Mi. + PageSize string `json:"pageSize,omitempty"` +} + +type Machine struct { + // QEMU machine type is the actual chipset of the VirtualMachineInstance. + // +optional + Type string `json:"type"` +} + +type Firmware struct { + // UUID reported by the vmi bios. + // Defaults to a random generated uid. + UUID types.UID `json:"uuid,omitempty"` + // Settings to control the bootloader that is used. + // +optional + Bootloader *Bootloader `json:"bootloader,omitempty"` + // The system-serial-number in SMBIOS + Serial string `json:"serial,omitempty"` + // Settings to set the kernel for booting. + // +optional + KernelBoot *KernelBoot `json:"kernelBoot,omitempty"` +} + +type Devices struct { + // Fall back to legacy virtio 0.9 support if virtio bus is selected on devices. + // This is helpful for old machines like CentOS6 or RHEL6 which + // do not understand virtio_non_transitional (virtio 1.0). + UseVirtioTransitional *bool `json:"useVirtioTransitional,omitempty"` + // DisableHotplug disabled the ability to hotplug disks. + DisableHotplug bool `json:"disableHotplug,omitempty"` + // Disks describes disks, cdroms and luns which are connected to the vmi. + Disks []Disk `json:"disks,omitempty"` + // Watchdog describes a watchdog device which can be added to the vmi. + Watchdog *Watchdog `json:"watchdog,omitempty"` + // Interfaces describe network interfaces which are added to the vmi. + Interfaces []Interface `json:"interfaces,omitempty"` + // Inputs describe input devices + Inputs []Input `json:"inputs,omitempty"` + // Whether to attach a pod network interface. Defaults to true. + AutoattachPodInterface *bool `json:"autoattachPodInterface,omitempty"` + // Whether to attach the default graphics device or not. + // VNC will not be available if set to false. Defaults to true. + AutoattachGraphicsDevice *bool `json:"autoattachGraphicsDevice,omitempty"` + // Whether to attach the default serial console or not. + // Serial console access will not be available if set to false. Defaults to true. + AutoattachSerialConsole *bool `json:"autoattachSerialConsole,omitempty"` + // Whether to attach the Memory balloon device with default period. + // Period can be adjusted in virt-config. + // Defaults to true. + // +optional + AutoattachMemBalloon *bool `json:"autoattachMemBalloon,omitempty"` + // Whether to have random number generator from host + // +optional + Rng *Rng `json:"rng,omitempty"` + // Whether or not to enable virtio multi-queue for block devices. + // Defaults to false. + // +optional + BlockMultiQueue *bool `json:"blockMultiQueue,omitempty"` + // If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature for network devices. The number of queues created depends on additional factors of the VirtualMachineInstance, like the number of guest CPUs. + // +optional + NetworkInterfaceMultiQueue *bool `json:"networkInterfaceMultiqueue,omitempty"` + //Whether to attach a GPU device to the vmi. + // +optional + // +listType=atomic + GPUs []GPU `json:"gpus,omitempty"` + // Filesystems describes filesystem which is connected to the vmi. + // +optional + // +listType=atomic + Filesystems []Filesystem `json:"filesystems,omitempty"` + //Whether to attach a host device to the vmi. + // +optional + // +listType=atomic + HostDevices []HostDevice `json:"hostDevices,omitempty"` + // To configure and access client devices such as redirecting USB + // +optional + ClientPassthrough *ClientPassthroughDevices `json:"clientPassthrough,omitempty"` + // Whether to emulate a sound device. + // +optional + Sound *SoundDevice `json:"sound,omitempty"` + // Whether to emulate a TPM device. + // +optional + TPM *TPMDevice `json:"tpm,omitempty"` +} + +// Represent a subset of client devices that can be accessed by VMI. At the +// moment only, USB devices using Usbredir's library and tooling. Another fit +// would be a smartcard with libcacard. +// +// The struct is currently empty as there is no immediate request for +// user-facing APIs. This structure simply turns on USB redirection of +// UsbClientPassthroughMaxNumberOf devices. +type ClientPassthroughDevices struct { +} + +// Represents the upper limit allowed by QEMU + KubeVirt. +const ( + UsbClientPassthroughMaxNumberOf = 4 +) + +// Represents the user's configuration to emulate sound cards in the VMI. +type SoundDevice struct { + // User's defined name for this sound device + Name string `json:"name"` + // We only support ich9 or ac97. + // If SoundDevice is not set: No sound card is emulated. + // If SoundDevice is set but Model is not: ich9 + // +optional + Model string `json:"model,omitempty"` +} + +type TPMDevice struct{} + +type Input struct { + // Bus indicates the bus of input device to emulate. + // Supported values: virtio, usb. + Bus string `json:"bus,omitempty"` + // Type indicated the type of input device. + // Supported values: tablet. + Type string `json:"type"` + // Name is the device name + Name string `json:"name"` +} + +type Filesystem struct { + // Name is the device name + Name string `json:"name"` + // Virtiofs is supported + Virtiofs *FilesystemVirtiofs `json:"virtiofs"` +} + +type FilesystemVirtiofs struct{} + +type GPU struct { + // Name of the GPU device as exposed by a device plugin + Name string `json:"name"` + DeviceName string `json:"deviceName"` + VirtualGPUOptions *VGPUOptions `json:"virtualGPUOptions,omitempty"` + // If specified, the virtual network interface address and its tag will be provided to the guest via config drive + // +optional + Tag string `json:"tag,omitempty"` +} + +type VGPUOptions struct { + Display *VGPUDisplayOptions `json:"display,omitempty"` +} + +type VGPUDisplayOptions struct { + // Enabled determines if a display addapter backed by a vGPU should be enabled or disabled on the guest. + // Defaults to true. + // +optional + Enabled *bool `json:"enabled,omitempty"` + // Enables a boot framebuffer, until the guest OS loads a real GPU driver + // Defaults to true. + // +optional + RamFB *FeatureState `json:"ramFB,omitempty"` +} + +type HostDevice struct { + Name string `json:"name"` + // DeviceName is the resource name of the host device exposed by a device plugin + DeviceName string `json:"deviceName"` + // If specified, the virtual network interface address and its tag will be provided to the guest via config drive + // +optional + Tag string `json:"tag,omitempty"` +} + +type Disk struct { + // Name is the device name + Name string `json:"name"` + // DiskDevice specifies as which device the disk should be added to the guest. + // Defaults to Disk. + DiskDevice `json:",inline"` + // BootOrder is an integer value > 0, used to determine ordering of boot devices. + // Lower values take precedence. + // Each disk or interface that has a boot order must have a unique value. + // Disks without a boot order are not tried if a disk with a boot order exists. + // +optional + BootOrder *uint `json:"bootOrder,omitempty"` + // Serial provides the ability to specify a serial number for the disk device. + // +optional + Serial string `json:"serial,omitempty"` + // dedicatedIOThread indicates this disk should have an exclusive IO Thread. + // Enabling this implies useIOThreads = true. + // Defaults to false. + // +optional + DedicatedIOThread *bool `json:"dedicatedIOThread,omitempty"` + // Cache specifies which kvm disk cache mode should be used. + // Supported values are: CacheNone, CacheWriteThrough. + // +optional + Cache DriverCache `json:"cache,omitempty"` + // IO specifies which QEMU disk IO mode should be used. + // Supported values are: native, default, threads. + // +optional + IO DriverIO `json:"io,omitempty"` + // If specified, disk address and its tag will be provided to the guest via config drive metadata + // +optional + Tag string `json:"tag,omitempty"` + // If specified, the virtual disk will be presented with the given block sizes. + // +optional + BlockSize *BlockSize `json:"blockSize,omitempty"` + // If specified the disk is made sharable and multiple write from different VMs are permitted + // +optional + Shareable *bool `json:"shareable,omitempty"` +} + +// CustomBlockSize represents the desired logical and physical block size for a VM disk. +type CustomBlockSize struct { + Logical uint `json:"logical"` + Physical uint `json:"physical"` +} + +// BlockSize provides the option to change the block size presented to the VM for a disk. +// Only one of its members may be specified. +type BlockSize struct { + Custom *CustomBlockSize `json:"custom,omitempty"` + MatchVolume *FeatureState `json:"matchVolume,omitempty"` +} + +// Represents the target of a volume to mount. +// Only one of its members may be specified. +type DiskDevice struct { + // Attach a volume as a disk to the vmi. + Disk *DiskTarget `json:"disk,omitempty"` + // Attach a volume as a LUN to the vmi. + LUN *LunTarget `json:"lun,omitempty"` + // Attach a volume as a cdrom to the vmi. + CDRom *CDRomTarget `json:"cdrom,omitempty"` +} + +type DiskBus string + +const ( + DiskBusSCSI DiskBus = "scsi" + DiskBusSATA DiskBus = "sata" + DiskBusVirtio DiskBus = "virtio" +) + +type DiskTarget struct { + // Bus indicates the type of disk device to emulate. + // supported values: virtio, sata, scsi. + Bus DiskBus `json:"bus,omitempty"` + // ReadOnly. + // Defaults to false. + ReadOnly bool `json:"readonly,omitempty"` + // If specified, the virtual disk will be placed on the guests pci address with the specified PCI address. For example: 0000:81:01.10 + // +optional + PciAddress string `json:"pciAddress,omitempty"` +} + +type LaunchSecurity struct { + // AMD Secure Encrypted Virtualization (SEV). + SEV *SEV `json:"sev,omitempty"` +} + +type SEV struct { +} + +type LunTarget struct { + // Bus indicates the type of disk device to emulate. + // supported values: virtio, sata, scsi. + Bus DiskBus `json:"bus,omitempty"` + // ReadOnly. + // Defaults to false. + ReadOnly bool `json:"readonly,omitempty"` +} + +// TrayState indicates if a tray of a cdrom is open or closed. +type TrayState string + +const ( + // TrayStateOpen indicates that the tray of a cdrom is open. + TrayStateOpen TrayState = "open" + // TrayStateClosed indicates that the tray of a cdrom is closed. + TrayStateClosed TrayState = "closed" +) + +type CDRomTarget struct { + // Bus indicates the type of disk device to emulate. + // supported values: virtio, sata, scsi. + Bus DiskBus `json:"bus,omitempty"` + // ReadOnly. + // Defaults to true. + ReadOnly *bool `json:"readonly,omitempty"` + // Tray indicates if the tray of the device is open or closed. + // Allowed values are "open" and "closed". + // Defaults to closed. + // +optional + Tray TrayState `json:"tray,omitempty"` +} + +// Volume represents a named volume in a vmi. +type Volume struct { + // Volume's name. + // Must be a DNS_LABEL and unique within the vmi. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + Name string `json:"name"` + // VolumeSource represents the location and type of the mounted volume. + // Defaults to Disk, if no type is specified. + VolumeSource `json:",inline"` +} + +// Represents the source of a volume to mount. +// Only one of its members may be specified. +type VolumeSource struct { + // HostDisk represents a disk created on the cluster level + // +optional + HostDisk *HostDisk `json:"hostDisk,omitempty"` + // PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. + // Directly attached to the vmi via qemu. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims + // +optional + PersistentVolumeClaim *PersistentVolumeClaimVolumeSource `json:"persistentVolumeClaim,omitempty"` + // CloudInitNoCloud represents a cloud-init NoCloud user-data source. + // The NoCloud data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. + // More info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html + // +optional + CloudInitNoCloud *CloudInitNoCloudSource `json:"cloudInitNoCloud,omitempty"` + // CloudInitConfigDrive represents a cloud-init Config Drive user-data source. + // The Config Drive data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. + // More info: https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html + // +optional + CloudInitConfigDrive *CloudInitConfigDriveSource `json:"cloudInitConfigDrive,omitempty"` + // Represents a Sysprep volume source. + // +optional + Sysprep *SysprepSource `json:"sysprep,omitempty"` + // ContainerDisk references a docker image, embedding a qcow or raw disk. + // More info: https://kubevirt.gitbooks.io/user-guide/registry-disk.html + // +optional + ContainerDisk *ContainerDiskSource `json:"containerDisk,omitempty"` + // Ephemeral is a special volume source that "wraps" specified source and provides copy-on-write image on top of it. + // +optional + Ephemeral *EphemeralVolumeSource `json:"ephemeral,omitempty"` + // EmptyDisk represents a temporary disk which shares the vmis lifecycle. + // More info: https://kubevirt.gitbooks.io/user-guide/disks-and-volumes.html + // +optional + EmptyDisk *EmptyDiskSource `json:"emptyDisk,omitempty"` + // DataVolume represents the dynamic creation a PVC for this volume as well as + // the process of populating that PVC with a disk image. + // +optional + DataVolume *DataVolumeSource `json:"dataVolume,omitempty"` + // ConfigMapSource represents a reference to a ConfigMap in the same namespace. + // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ + // +optional + ConfigMap *ConfigMapVolumeSource `json:"configMap,omitempty"` + // SecretVolumeSource represents a reference to a secret data in the same namespace. + // More info: https://kubernetes.io/docs/concepts/configuration/secret/ + // +optional + Secret *SecretVolumeSource `json:"secret,omitempty"` + // DownwardAPI represents downward API about the pod that should populate this volume + // +optional + DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"` + // ServiceAccountVolumeSource represents a reference to a service account. + // There can only be one volume of this type! + // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + // +optional + ServiceAccount *ServiceAccountVolumeSource `json:"serviceAccount,omitempty"` + // DownwardMetrics adds a very small disk to VMIs which contains a limited view of host and guest + // metrics. The disk content is compatible with vhostmd (https://github.com/vhostmd/vhostmd) and vm-dump-metrics. + DownwardMetrics *DownwardMetricsVolumeSource `json:"downwardMetrics,omitempty"` + // MemoryDump is attached to the virt launcher and is populated with a memory dump of the vmi + MemoryDump *MemoryDumpVolumeSource `json:"memoryDump,omitempty"` +} + +// HotplugVolumeSource Represents the source of a volume to mount which are capable +// of being hotplugged on a live running VMI. +// Only one of its members may be specified. +type HotplugVolumeSource struct { + // PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. + // Directly attached to the vmi via qemu. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims + // +optional + PersistentVolumeClaim *PersistentVolumeClaimVolumeSource `json:"persistentVolumeClaim,omitempty"` + // DataVolume represents the dynamic creation a PVC for this volume as well as + // the process of populating that PVC with a disk image. + // +optional + DataVolume *DataVolumeSource `json:"dataVolume,omitempty"` +} + +type DataVolumeSource struct { + // Name represents the name of the DataVolume in the same namespace + Name string `json:"name"` + // Hotpluggable indicates whether the volume can be hotplugged and hotunplugged. + // +optional + Hotpluggable bool `json:"hotpluggable,omitempty"` +} + +// PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. +// Directly attached to the vmi via qemu. +// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims +type PersistentVolumeClaimVolumeSource struct { + v1.PersistentVolumeClaimVolumeSource `json:",inline"` + // Hotpluggable indicates whether the volume can be hotplugged and hotunplugged. + // +optional + Hotpluggable bool `json:"hotpluggable,omitempty"` +} + +type MemoryDumpVolumeSource struct { + // PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. + // Directly attached to the virt launcher + // +optional + PersistentVolumeClaimVolumeSource `json:",inline"` +} + +type EphemeralVolumeSource struct { + // PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. + // Directly attached to the vmi via qemu. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims + // +optional + PersistentVolumeClaim *v1.PersistentVolumeClaimVolumeSource `json:"persistentVolumeClaim,omitempty"` +} + +// EmptyDisk represents a temporary disk which shares the vmis lifecycle. +type EmptyDiskSource struct { + // Capacity of the sparse disk. + Capacity resource.Quantity `json:"capacity"` +} + +// Represents a docker image with an embedded disk. +type ContainerDiskSource struct { + // Image is the name of the image with the embedded disk. + Image string `json:"image"` + // ImagePullSecret is the name of the Docker registry secret required to pull the image. The secret must already exist. + ImagePullSecret string `json:"imagePullSecret,omitempty"` + // Path defines the path to disk file in the container + Path string `json:"path,omitempty"` + // Image pull policy. + // One of Always, Never, IfNotPresent. + // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + // +optional + ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"` +} + +// Exactly one of its members must be set. +type ClockOffset struct { + // UTC sets the guest clock to UTC on each boot. If an offset is specified, + // guest changes to the clock will be kept during reboots and are not reset. + UTC *ClockOffsetUTC `json:"utc,omitempty"` + // Timezone sets the guest clock to the specified timezone. + // Zone name follows the TZ environment variable format (e.g. 'America/New_York'). + Timezone *ClockOffsetTimezone `json:"timezone,omitempty"` +} + +// UTC sets the guest clock to UTC on each boot. +type ClockOffsetUTC struct { + // OffsetSeconds specifies an offset in seconds, relative to UTC. If set, + // guest changes to the clock will be kept during reboots and not reset. + OffsetSeconds *int `json:"offsetSeconds,omitempty"` +} + +// ClockOffsetTimezone sets the guest clock to the specified timezone. +// Zone name follows the TZ environment variable format (e.g. 'America/New_York'). +type ClockOffsetTimezone string + +// Represents the clock and timers of a vmi. +// +kubebuilder:pruning:PreserveUnknownFields +type Clock struct { + // ClockOffset allows specifying the UTC offset or the timezone of the guest clock. + ClockOffset `json:",inline"` + // Timer specifies whih timers are attached to the vmi. + // +optional + Timer *Timer `json:"timer"` +} + +// Represents all available timers in a vmi. +type Timer struct { + // HPET (High Precision Event Timer) - multiple timers with periodic interrupts. + HPET *HPETTimer `json:"hpet,omitempty"` + // KVM (KVM clock) - lets guests read the host’s wall clock time (paravirtualized). For linux guests. + KVM *KVMTimer `json:"kvm,omitempty"` + // PIT (Programmable Interval Timer) - a timer with periodic interrupts. + PIT *PITTimer `json:"pit,omitempty"` + // RTC (Real Time Clock) - a continuously running timer with periodic interrupts. + RTC *RTCTimer `json:"rtc,omitempty"` + // Hyperv (Hypervclock) - lets guests read the host’s wall clock time (paravirtualized). For windows guests. + Hyperv *HypervTimer `json:"hyperv,omitempty"` +} + +// HPETTickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. +type HPETTickPolicy string + +// PITTickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. +type PITTickPolicy string + +// RTCTickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. +type RTCTickPolicy string + +const ( + // HPETTickPolicyDelay delivers ticks at a constant rate. The guest time will + // be delayed due to the late tick + HPETTickPolicyDelay HPETTickPolicy = "delay" + // HPETTickPolicyCatchup Delivers ticks at a higher rate to catch up with the + // missed tick. The guest time should not be delayed once catchup is complete + HPETTickPolicyCatchup HPETTickPolicy = "catchup" + // HPETTickPolicyMerge merges the missed tick(s) into one tick and inject. The + // guest time may be delayed, depending on how the OS reacts to the merging + // of ticks. + HPETTickPolicyMerge HPETTickPolicy = "merge" + // HPETTickPolicyDiscard discards all missed ticks. + HPETTickPolicyDiscard HPETTickPolicy = "discard" + + // PITTickPolicyDelay delivers ticks at a constant rate. The guest time will + // be delayed due to the late tick. + PITTickPolicyDelay PITTickPolicy = "delay" + // PITTickPolicyCatchup Delivers ticks at a higher rate to catch up with the + // missed tick. The guest time should not be delayed once catchup is complete. + PITTickPolicyCatchup PITTickPolicy = "catchup" + // PITTickPolicyDiscard discards all missed ticks. + PITTickPolicyDiscard PITTickPolicy = "discard" + + // RTCTickPolicyDelay delivers ticks at a constant rate. The guest time will + // be delayed due to the late tick. + RTCTickPolicyDelay RTCTickPolicy = "delay" + // RTCTickPolicyCatchup Delivers ticks at a higher rate to catch up with the + // missed tick. The guest time should not be delayed once catchup is complete. + RTCTickPolicyCatchup RTCTickPolicy = "catchup" +) + +// RTCTimerTrack specifies from which source to track the time. +type RTCTimerTrack string + +const ( + // TrackGuest tracks the guest time. + TrackGuest RTCTimerTrack = "guest" + // TrackWall tracks the host time. + TrackWall RTCTimerTrack = "wall" +) + +type RTCTimer struct { + // TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. + // One of "delay", "catchup". + TickPolicy RTCTickPolicy `json:"tickPolicy,omitempty"` + // Enabled set to false makes sure that the machine type or a preset can't add the timer. + // Defaults to true. + // +optional + Enabled *bool `json:"present,omitempty"` + // Track the guest or the wall clock. + Track RTCTimerTrack `json:"track,omitempty"` +} + +type HPETTimer struct { + // TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. + // One of "delay", "catchup", "merge", "discard". + TickPolicy HPETTickPolicy `json:"tickPolicy,omitempty"` + // Enabled set to false makes sure that the machine type or a preset can't add the timer. + // Defaults to true. + // +optional + Enabled *bool `json:"present,omitempty"` +} + +type PITTimer struct { + // TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. + // One of "delay", "catchup", "discard". + TickPolicy PITTickPolicy `json:"tickPolicy,omitempty"` + // Enabled set to false makes sure that the machine type or a preset can't add the timer. + // Defaults to true. + // +optional + Enabled *bool `json:"present,omitempty"` +} + +type KVMTimer struct { + // Enabled set to false makes sure that the machine type or a preset can't add the timer. + // Defaults to true. + // +optional + Enabled *bool `json:"present,omitempty"` +} + +type HypervTimer struct { + // Enabled set to false makes sure that the machine type or a preset can't add the timer. + // Defaults to true. + // +optional + Enabled *bool `json:"present,omitempty"` +} + +type Features struct { + // ACPI enables/disables ACPI inside the guest. + // Defaults to enabled. + // +optional + ACPI FeatureState `json:"acpi,omitempty"` + // Defaults to the machine type setting. + // +optional + APIC *FeatureAPIC `json:"apic,omitempty"` + // Defaults to the machine type setting. + // +optional + Hyperv *FeatureHyperv `json:"hyperv,omitempty"` + // SMM enables/disables System Management Mode. + // TSEG not yet implemented. + // +optional + SMM *FeatureState `json:"smm,omitempty"` + // Configure how KVM presence is exposed to the guest. + // +optional + KVM *FeatureKVM `json:"kvm,omitempty"` + // Notify the guest that the host supports paravirtual spinlocks. + // For older kernels this feature should be explicitly disabled. + // +optional + Pvspinlock *FeatureState `json:"pvspinlock,omitempty"` +} + +type SyNICTimer struct { + Enabled *bool `json:"enabled,omitempty"` + Direct *FeatureState `json:"direct,omitempty"` +} + +// Represents if a feature is enabled or disabled. +type FeatureState struct { + // Enabled determines if the feature should be enabled or disabled on the guest. + // Defaults to true. + // +optional + Enabled *bool `json:"enabled,omitempty"` +} + +type FeatureAPIC struct { + // Enabled determines if the feature should be enabled or disabled on the guest. + // Defaults to true. + // +optional + Enabled *bool `json:"enabled,omitempty"` + // EndOfInterrupt enables the end of interrupt notification in the guest. + // Defaults to false. + // +optional + EndOfInterrupt bool `json:"endOfInterrupt,omitempty"` +} + +type FeatureSpinlocks struct { + // Enabled determines if the feature should be enabled or disabled on the guest. + // Defaults to true. + // +optional + Enabled *bool `json:"enabled,omitempty"` + // Retries indicates the number of retries. + // Must be a value greater or equal 4096. + // Defaults to 4096. + // +optional + Retries *uint32 `json:"spinlocks,omitempty"` +} + +type FeatureVendorID struct { + // Enabled determines if the feature should be enabled or disabled on the guest. + // Defaults to true. + // +optional + Enabled *bool `json:"enabled,omitempty"` + // VendorID sets the hypervisor vendor id, visible to the vmi. + // String up to twelve characters. + VendorID string `json:"vendorid,omitempty"` +} + +// Hyperv specific features. +type FeatureHyperv struct { + // Relaxed instructs the guest OS to disable watchdog timeouts. + // Defaults to the machine type setting. + // +optional + Relaxed *FeatureState `json:"relaxed,omitempty"` + // VAPIC improves the paravirtualized handling of interrupts. + // Defaults to the machine type setting. + // +optional + VAPIC *FeatureState `json:"vapic,omitempty"` + // Spinlocks allows to configure the spinlock retry attempts. + // +optional + Spinlocks *FeatureSpinlocks `json:"spinlocks,omitempty"` + // VPIndex enables the Virtual Processor Index to help windows identifying virtual processors. + // Defaults to the machine type setting. + // +optional + VPIndex *FeatureState `json:"vpindex,omitempty"` + // Runtime improves the time accounting to improve scheduling in the guest. + // Defaults to the machine type setting. + // +optional + Runtime *FeatureState `json:"runtime,omitempty"` + // SyNIC enables the Synthetic Interrupt Controller. + // Defaults to the machine type setting. + // +optional + SyNIC *FeatureState `json:"synic,omitempty"` + // SyNICTimer enables Synthetic Interrupt Controller Timers, reducing CPU load. + // Defaults to the machine type setting. + // +optional + SyNICTimer *SyNICTimer `json:"synictimer,omitempty"` + // Reset enables Hyperv reboot/reset for the vmi. Requires synic. + // Defaults to the machine type setting. + // +optional + Reset *FeatureState `json:"reset,omitempty"` + // VendorID allows setting the hypervisor vendor id. + // Defaults to the machine type setting. + // +optional + VendorID *FeatureVendorID `json:"vendorid,omitempty"` + // Frequencies improves the TSC clock source handling for Hyper-V on KVM. + // Defaults to the machine type setting. + // +optional + Frequencies *FeatureState `json:"frequencies,omitempty"` + // Reenlightenment enables the notifications on TSC frequency changes. + // Defaults to the machine type setting. + // +optional + Reenlightenment *FeatureState `json:"reenlightenment,omitempty"` + // TLBFlush improves performances in overcommited environments. Requires vpindex. + // Defaults to the machine type setting. + // +optional + TLBFlush *FeatureState `json:"tlbflush,omitempty"` + // IPI improves performances in overcommited environments. Requires vpindex. + // Defaults to the machine type setting. + // +optional + IPI *FeatureState `json:"ipi,omitempty"` + // EVMCS Speeds up L2 vmexits, but disables other virtualization features. Requires vapic. + // Defaults to the machine type setting. + // +optional + EVMCS *FeatureState `json:"evmcs,omitempty"` +} + +type FeatureKVM struct { + // Hide the KVM hypervisor from standard MSR based discovery. + // Defaults to false + Hidden bool `json:"hidden,omitempty"` +} + +// WatchdogAction defines the watchdog action, if a watchdog gets triggered. +type WatchdogAction string + +const ( + // WatchdogActionPoweroff will poweroff the vmi if the watchdog gets triggered. + WatchdogActionPoweroff WatchdogAction = "poweroff" + // WatchdogActionReset will reset the vmi if the watchdog gets triggered. + WatchdogActionReset WatchdogAction = "reset" + // WatchdogActionShutdown will shutdown the vmi if the watchdog gets triggered. + WatchdogActionShutdown WatchdogAction = "shutdown" +) + +// Named watchdog device. +type Watchdog struct { + // Name of the watchdog. + Name string `json:"name"` + // WatchdogDevice contains the watchdog type and actions. + // Defaults to i6300esb. + WatchdogDevice `json:",inline"` +} + +// Hardware watchdog device. +// Exactly one of its members must be set. +type WatchdogDevice struct { + // i6300esb watchdog device. + // +optional + I6300ESB *I6300ESBWatchdog `json:"i6300esb,omitempty"` +} + +// i6300esb watchdog device. +type I6300ESBWatchdog struct { + // The action to take. Valid values are poweroff, reset, shutdown. + // Defaults to reset. + Action WatchdogAction `json:"action,omitempty"` +} + +type Interface struct { + // Logical name of the interface as well as a reference to the associated networks. + // Must match the Name of a Network. + Name string `json:"name"` + // Interface model. + // One of: e1000, e1000e, ne2k_pci, pcnet, rtl8139, virtio. + // Defaults to virtio. + // TODO:(ihar) switch to enums once opengen-api supports them. See: https://github.com/kubernetes/kube-openapi/issues/51 + Model string `json:"model,omitempty"` + // BindingMethod specifies the method which will be used to connect the interface to the guest. + // Defaults to Bridge. + InterfaceBindingMethod `json:",inline"` + // List of ports to be forwarded to the virtual machine. + Ports []Port `json:"ports,omitempty"` + // Interface MAC address. For example: de:ad:00:00:be:af or DE-AD-00-00-BE-AF. + MacAddress string `json:"macAddress,omitempty"` + // BootOrder is an integer value > 0, used to determine ordering of boot devices. + // Lower values take precedence. + // Each interface or disk that has a boot order must have a unique value. + // Interfaces without a boot order are not tried. + // +optional + BootOrder *uint `json:"bootOrder,omitempty"` + // If specified, the virtual network interface will be placed on the guests pci address with the specified PCI address. For example: 0000:81:01.10 + // +optional + PciAddress string `json:"pciAddress,omitempty"` + // If specified the network interface will pass additional DHCP options to the VMI + // +optional + DHCPOptions *DHCPOptions `json:"dhcpOptions,omitempty"` + // If specified, the virtual network interface address and its tag will be provided to the guest via config drive + // +optional + Tag string `json:"tag,omitempty"` +} + +// Extra DHCP options to use in the interface. +type DHCPOptions struct { + // If specified will pass option 67 to interface's DHCP server + // +optional + BootFileName string `json:"bootFileName,omitempty"` + // If specified will pass option 66 to interface's DHCP server + // +optional + TFTPServerName string `json:"tftpServerName,omitempty"` + // If specified will pass the configured NTP server to the VM via DHCP option 042. + // +optional + NTPServers []string `json:"ntpServers,omitempty"` + // If specified will pass extra DHCP options for private use, range: 224-254 + // +optional + PrivateOptions []DHCPPrivateOptions `json:"privateOptions,omitempty"` +} + +func (d *DHCPOptions) UnmarshalJSON(data []byte) error { + type DHCPOptionsAlias DHCPOptions + var dhcpOptionsAlias DHCPOptionsAlias + + if err := json.Unmarshal(data, &dhcpOptionsAlias); err != nil { + return err + } + + for i, ntpServer := range dhcpOptionsAlias.NTPServers { + if sanitizedIP, err := sanitizeIP(ntpServer); err == nil { + dhcpOptionsAlias.NTPServers[i] = sanitizedIP + } + } + + *d = DHCPOptions(dhcpOptionsAlias) + return nil +} + +// DHCPExtraOptions defines Extra DHCP options for a VM. +type DHCPPrivateOptions struct { + // Option is an Integer value from 224-254 + // Required. + Option int `json:"option"` + // Value is a String value for the Option provided + // Required. + Value string `json:"value"` +} + +// Represents the method which will be used to connect the interface to the guest. +// Only one of its members may be specified. +type InterfaceBindingMethod struct { + Bridge *InterfaceBridge `json:"bridge,omitempty"` + Slirp *InterfaceSlirp `json:"slirp,omitempty"` + Masquerade *InterfaceMasquerade `json:"masquerade,omitempty"` + SRIOV *InterfaceSRIOV `json:"sriov,omitempty"` + Macvtap *InterfaceMacvtap `json:"macvtap,omitempty"` +} + +// InterfaceBridge connects to a given network via a linux bridge. +type InterfaceBridge struct{} + +// InterfaceSlirp connects to a given network using QEMU user networking mode. +type InterfaceSlirp struct{} + +// InterfaceMasquerade connects to a given network using netfilter rules to nat the traffic. +type InterfaceMasquerade struct{} + +// InterfaceSRIOV connects to a given network by passing-through an SR-IOV PCI device via vfio. +type InterfaceSRIOV struct{} + +// InterfaceMacvtap connects to a given network by extending the Kubernetes node's L2 networks via a macvtap interface. +type InterfaceMacvtap struct{} + +// Port represents a port to expose from the virtual machine. +// Default protocol TCP. +// The port field is mandatory +type Port struct { + // If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + // named port in a pod must have a unique name. Name for the port that can be + // referred to by services. + // +optional + Name string `json:"name,omitempty"` + // Protocol for port. Must be UDP or TCP. + // Defaults to "TCP". + // +optional + Protocol string `json:"protocol,omitempty"` + // Number of port to expose for the virtual machine. + // This must be a valid port number, 0 < x < 65536. + Port int32 `json:"port"` +} + +type AccessCredentialSecretSource struct { + // SecretName represents the name of the secret in the VMI's namespace + SecretName string `json:"secretName"` +} + +type ConfigDriveSSHPublicKeyAccessCredentialPropagation struct{} + +// AuthorizedKeysFile represents a path within the guest +// that ssh public keys should be propagated to +type AuthorizedKeysFile struct { + // FilePath represents the place on the guest that the authorized_keys + // file should be writen to. This is expected to be a full path including + // both the base directory and file name. + FilePath string `json:"filePath"` +} + +type QemuGuestAgentUserPasswordAccessCredentialPropagation struct{} + +type QemuGuestAgentSSHPublicKeyAccessCredentialPropagation struct { + // Users represents a list of guest users that should have the ssh public keys + // added to their authorized_keys file. + // +listType=set + Users []string `json:"users"` +} + +// SSHPublicKeyAccessCredentialSource represents where to retrieve the ssh key +// credentials +// Only one of its members may be specified. +type SSHPublicKeyAccessCredentialSource struct { + // Secret means that the access credential is pulled from a kubernetes secret + // +optional + Secret *AccessCredentialSecretSource `json:"secret,omitempty"` +} + +// SSHPublicKeyAccessCredentialPropagationMethod represents the method used to +// inject a ssh public key into the vm guest. +// Only one of its members may be specified. +type SSHPublicKeyAccessCredentialPropagationMethod struct { + // ConfigDrivePropagation means that the ssh public keys are injected + // into the VM using metadata using the configDrive cloud-init provider + // +optional + ConfigDrive *ConfigDriveSSHPublicKeyAccessCredentialPropagation `json:"configDrive,omitempty"` + + // QemuGuestAgentAccessCredentailPropagation means ssh public keys are + // dynamically injected into the vm at runtime via the qemu guest agent. + // This feature requires the qemu guest agent to be running within the guest. + // +optional + QemuGuestAgent *QemuGuestAgentSSHPublicKeyAccessCredentialPropagation `json:"qemuGuestAgent,omitempty"` +} + +// SSHPublicKeyAccessCredential represents a source and propagation method for +// injecting ssh public keys into a vm guest +type SSHPublicKeyAccessCredential struct { + // Source represents where the public keys are pulled from + Source SSHPublicKeyAccessCredentialSource `json:"source"` + + // PropagationMethod represents how the public key is injected into the vm guest. + PropagationMethod SSHPublicKeyAccessCredentialPropagationMethod `json:"propagationMethod"` +} + +// UserPasswordAccessCredentialSource represents where to retrieve the user password +// credentials +// Only one of its members may be specified. +type UserPasswordAccessCredentialSource struct { + // Secret means that the access credential is pulled from a kubernetes secret + // +optional + Secret *AccessCredentialSecretSource `json:"secret,omitempty"` +} + +// UserPasswordAccessCredentialPropagationMethod represents the method used to +// inject a user passwords into the vm guest. +// Only one of its members may be specified. +type UserPasswordAccessCredentialPropagationMethod struct { + // QemuGuestAgentAccessCredentailPropagation means passwords are + // dynamically injected into the vm at runtime via the qemu guest agent. + // This feature requires the qemu guest agent to be running within the guest. + // +optional + QemuGuestAgent *QemuGuestAgentUserPasswordAccessCredentialPropagation `json:"qemuGuestAgent,omitempty"` +} + +// UserPasswordAccessCredential represents a source and propagation method for +// injecting user passwords into a vm guest +// Only one of its members may be specified. +type UserPasswordAccessCredential struct { + // Source represents where the user passwords are pulled from + Source UserPasswordAccessCredentialSource `json:"source"` + + // propagationMethod represents how the user passwords are injected into the vm guest. + PropagationMethod UserPasswordAccessCredentialPropagationMethod `json:"propagationMethod"` +} + +// AccessCredential represents a credential source that can be used to +// authorize remote access to the vm guest +// Only one of its members may be specified. +type AccessCredential struct { + // SSHPublicKey represents the source and method of applying a ssh public + // key into a guest virtual machine. + // +optional + SSHPublicKey *SSHPublicKeyAccessCredential `json:"sshPublicKey,omitempty"` + // UserPassword represents the source and method for applying a guest user's + // password + // +optional + UserPassword *UserPasswordAccessCredential `json:"userPassword,omitempty"` +} + +// Network represents a network type and a resource that should be connected to the vm. +type Network struct { + // Network name. + // Must be a DNS_LABEL and unique within the vm. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + Name string `json:"name"` + // NetworkSource represents the network type and the source interface that should be connected to the virtual machine. + // Defaults to Pod, if no type is specified. + NetworkSource `json:",inline"` +} + +// Represents the source resource that will be connected to the vm. +// Only one of its members may be specified. +type NetworkSource struct { + Pod *PodNetwork `json:"pod,omitempty"` + Multus *MultusNetwork `json:"multus,omitempty"` +} + +// Represents the stock pod network interface. +type PodNetwork struct { + // CIDR for vm network. + // Default 10.0.2.0/24 if not specified. + VMNetworkCIDR string `json:"vmNetworkCIDR,omitempty"` + + // IPv6 CIDR for the vm network. + // Defaults to fd10:0:2::/120 if not specified. + VMIPv6NetworkCIDR string `json:"vmIPv6NetworkCIDR,omitempty"` +} + +func (podNet *PodNetwork) UnmarshalJSON(data []byte) error { + type PodNetworkAlias PodNetwork + var podNetAlias PodNetworkAlias + + if err := json.Unmarshal(data, &podNetAlias); err != nil { + return err + } + + if sanitizedCIDR, err := sanitizeCIDR(podNetAlias.VMNetworkCIDR); err == nil { + podNetAlias.VMNetworkCIDR = sanitizedCIDR + } + + *podNet = PodNetwork(podNetAlias) + return nil +} + +// Rng represents the random device passed from host +type Rng struct { +} + +// Represents the multus cni network. +type MultusNetwork struct { + // References to a NetworkAttachmentDefinition CRD object. Format: + // , /. If namespace is not + // specified, VMI namespace is assumed. + NetworkName string `json:"networkName"` + + // Select the default network and add it to the + // multus-cni.io/default-network annotation. + Default bool `json:"default,omitempty"` +} diff --git a/vendor/kubevirt.io/api/core/v1/schema_swagger_generated.go b/vendor/kubevirt.io/api/core/v1/schema_swagger_generated.go new file mode 100644 index 00000000..1a5b2cf3 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/schema_swagger_generated.go @@ -0,0 +1,805 @@ +// Code generated by swagger-doc. DO NOT EDIT. + +package v1 + +func (HostDisk) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents a disk created on the cluster level", + "path": "The path to HostDisk image located on the cluster", + "type": "Contains information if disk.img exists or should be created\nallowed options are 'Disk' and 'DiskOrCreate'", + "capacity": "Capacity of the sparse disk\n+optional", + "shared": "Shared indicate whether the path is shared between nodes", + } +} + +func (ConfigMapVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ConfigMapVolumeSource adapts a ConfigMap into a volume.\nMore info: https://kubernetes.io/docs/concepts/storage/volumes/#configmap", + "optional": "Specify whether the ConfigMap or it's keys must be defined\n+optional", + "volumeLabel": "The volume label of the resulting disk inside the VMI.\nDifferent bootstrapping mechanisms require different values.\nTypical values are \"cidata\" (cloud-init), \"config-2\" (cloud-init) or \"OEMDRV\" (kickstart).\n+optional", + } +} + +func (SecretVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "SecretVolumeSource adapts a Secret into a volume.", + "secretName": "Name of the secret in the pod's namespace to use.\nMore info: https://kubernetes.io/docs/concepts/storage/volumes#secret\n+optional", + "optional": "Specify whether the Secret or it's keys must be defined\n+optional", + "volumeLabel": "The volume label of the resulting disk inside the VMI.\nDifferent bootstrapping mechanisms require different values.\nTypical values are \"cidata\" (cloud-init), \"config-2\" (cloud-init) or \"OEMDRV\" (kickstart).\n+optional", + } +} + +func (DownwardAPIVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DownwardAPIVolumeSource represents a volume containing downward API info.", + "fields": "Fields is a list of downward API volume file\n+optional", + "volumeLabel": "The volume label of the resulting disk inside the VMI.\nDifferent bootstrapping mechanisms require different values.\nTypical values are \"cidata\" (cloud-init), \"config-2\" (cloud-init) or \"OEMDRV\" (kickstart).\n+optional", + } +} + +func (ServiceAccountVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ServiceAccountVolumeSource adapts a ServiceAccount into a volume.", + "serviceAccountName": "Name of the service account in the pod's namespace to use.\nMore info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", + } +} + +func (DownwardMetricsVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DownwardMetricsVolumeSource adds a very small disk to VMIs which contains a limited view of host and guest\nmetrics. The disk content is compatible with vhostmd (https://github.com/vhostmd/vhostmd) and vm-dump-metrics.", + } +} + +func (SysprepSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents a Sysprep volume source.", + "secret": "Secret references a k8s Secret that contains Sysprep answer file named autounattend.xml that should be attached as disk of CDROM type.\n+ optional", + "configMap": "ConfigMap references a ConfigMap that contains Sysprep answer file named autounattend.xml that should be attached as disk of CDROM type.\n+ optional", + } +} + +func (CloudInitNoCloudSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents a cloud-init nocloud user data source.\nMore info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html", + "secretRef": "UserDataSecretRef references a k8s secret that contains NoCloud userdata.\n+ optional", + "userDataBase64": "UserDataBase64 contains NoCloud cloud-init userdata as a base64 encoded string.\n+ optional", + "userData": "UserData contains NoCloud inline cloud-init userdata.\n+ optional", + "networkDataSecretRef": "NetworkDataSecretRef references a k8s secret that contains NoCloud networkdata.\n+ optional", + "networkDataBase64": "NetworkDataBase64 contains NoCloud cloud-init networkdata as a base64 encoded string.\n+ optional", + "networkData": "NetworkData contains NoCloud inline cloud-init networkdata.\n+ optional", + } +} + +func (CloudInitConfigDriveSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents a cloud-init config drive user data source.\nMore info: https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html", + "secretRef": "UserDataSecretRef references a k8s secret that contains config drive userdata.\n+ optional", + "userDataBase64": "UserDataBase64 contains config drive cloud-init userdata as a base64 encoded string.\n+ optional", + "userData": "UserData contains config drive inline cloud-init userdata.\n+ optional", + "networkDataSecretRef": "NetworkDataSecretRef references a k8s secret that contains config drive networkdata.\n+ optional", + "networkDataBase64": "NetworkDataBase64 contains config drive cloud-init networkdata as a base64 encoded string.\n+ optional", + "networkData": "NetworkData contains config drive inline cloud-init networkdata.\n+ optional", + } +} + +func (DomainSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "resources": "Resources describes the Compute Resources required by this vmi.", + "cpu": "CPU allow specified the detailed CPU topology inside the vmi.\n+optional", + "memory": "Memory allow specifying the VMI memory features.\n+optional", + "machine": "Machine type.\n+optional", + "firmware": "Firmware.\n+optional", + "clock": "Clock sets the clock and timers of the vmi.\n+optional", + "features": "Features like acpi, apic, hyperv, smm.\n+optional", + "devices": "Devices allows adding disks, network interfaces, and others", + "ioThreadsPolicy": "Controls whether or not disks will share IOThreads.\nOmitting IOThreadsPolicy disables use of IOThreads.\nOne of: shared, auto\n+optional", + "chassis": "Chassis specifies the chassis info passed to the domain.\n+optional", + "launchSecurity": "Launch Security setting of the vmi.\n+optional", + } +} + +func (Chassis) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Chassis specifies the chassis info passed to the domain.", + } +} + +func (Bootloader) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the firmware blob used to assist in the domain creation process.\nUsed for setting the QEMU BIOS file path for the libvirt domain.", + "bios": "If set (default), BIOS will be used.\n+optional", + "efi": "If set, EFI will be used instead of BIOS.\n+optional", + } +} + +func (BIOS) SwaggerDoc() map[string]string { + return map[string]string{ + "": "If set (default), BIOS will be used.", + "useSerial": "If set, the BIOS output will be transmitted over serial\n+optional", + } +} + +func (EFI) SwaggerDoc() map[string]string { + return map[string]string{ + "": "If set, EFI will be used instead of BIOS.", + "secureBoot": "If set, SecureBoot will be enabled and the OVMF roms will be swapped for\nSecureBoot-enabled ones.\nRequires SMM to be enabled.\nDefaults to true\n+optional", + } +} + +func (KernelBootContainer) SwaggerDoc() map[string]string { + return map[string]string{ + "": "If set, the VM will be booted from the defined kernel / initrd.", + "image": "Image that contains initrd / kernel files.", + "imagePullSecret": "ImagePullSecret is the name of the Docker registry secret required to pull the image. The secret must already exist.\n+optional", + "imagePullPolicy": "Image pull policy.\nOne of Always, Never, IfNotPresent.\nDefaults to Always if :latest tag is specified, or IfNotPresent otherwise.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/containers/images#updating-images\n+optional", + "kernelPath": "The fully-qualified path to the kernel image in the host OS\n+optional", + "initrdPath": "the fully-qualified path to the ramdisk image in the host OS\n+optional", + } +} + +func (KernelBoot) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the firmware blob used to assist in the kernel boot process.\nUsed for setting the kernel, initrd and command line arguments", + "kernelArgs": "Arguments to be passed to the kernel at boot time", + "container": "Container defines the container that containes kernel artifacts", + } +} + +func (ResourceRequirements) SwaggerDoc() map[string]string { + return map[string]string{ + "requests": "Requests is a description of the initial vmi resources.\nValid resource keys are \"memory\" and \"cpu\".\n+optional", + "limits": "Limits describes the maximum amount of compute resources allowed.\nValid resource keys are \"memory\" and \"cpu\".\n+optional", + "overcommitGuestOverhead": "Don't ask the scheduler to take the guest-management overhead into account. Instead\nput the overhead only into the container's memory limit. This can lead to crashes if\nall memory is in use on a node. Defaults to false.", + } +} + +func (CPU) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CPU allows specifying the CPU topology.", + "cores": "Cores specifies the number of cores inside the vmi.\nMust be a value greater or equal 1.", + "sockets": "Sockets specifies the number of sockets inside the vmi.\nMust be a value greater or equal 1.", + "threads": "Threads specifies the number of threads inside the vmi.\nMust be a value greater or equal 1.", + "model": "Model specifies the CPU model inside the VMI.\nList of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map.\nIt is possible to specify special cases like \"host-passthrough\" to get the same CPU as the node\nand \"host-model\" to get CPU closest to the node one.\nDefaults to host-model.\n+optional", + "features": "Features specifies the CPU features list inside the VMI.\n+optional", + "dedicatedCpuPlacement": "DedicatedCPUPlacement requests the scheduler to place the VirtualMachineInstance on a node\nwith enough dedicated pCPUs and pin the vCPUs to it.\n+optional", + "numa": "NUMA allows specifying settings for the guest NUMA topology\n+optional", + "isolateEmulatorThread": "IsolateEmulatorThread requests one more dedicated pCPU to be allocated for the VMI to place\nthe emulator thread on it.\n+optional", + "realtime": "Realtime instructs the virt-launcher to tune the VMI for lower latency, optional for real time workloads\n+optional", + } +} + +func (Realtime) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Realtime holds the tuning knobs specific for realtime workloads.", + "mask": "Mask defines the vcpu mask expression that defines which vcpus are used for realtime. Format matches libvirt's expressions.\nExample: \"0-3,^1\",\"0,2,3\",\"2-3\"\n+optional", + } +} + +func (NUMAGuestMappingPassthrough) SwaggerDoc() map[string]string { + return map[string]string{ + "": "NUMAGuestMappingPassthrough instructs kubevirt to model numa topology which is compatible with the CPU pinning on the guest.\nThis will result in a subset of the node numa topology being passed through, ensuring that virtual numa nodes and their memory\nnever cross boundaries coming from the node numa mapping.", + } +} + +func (NUMA) SwaggerDoc() map[string]string { + return map[string]string{ + "guestMappingPassthrough": "GuestMappingPassthrough will create an efficient guest topology based on host CPUs exclusively assigned to a pod.\nThe created topology ensures that memory and CPUs on the virtual numa nodes never cross boundaries of host numa nodes.\n+opitonal", + } +} + +func (CPUFeature) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CPUFeature allows specifying a CPU feature.", + "name": "Name of the CPU feature", + "policy": "Policy is the CPU feature attribute which can have the following attributes:\nforce - The virtual CPU will claim the feature is supported regardless of it being supported by host CPU.\nrequire - Guest creation will fail unless the feature is supported by the host CPU or the hypervisor is able to emulate it.\noptional - The feature will be supported by virtual CPU if and only if it is supported by host CPU.\ndisable - The feature will not be supported by virtual CPU.\nforbid - Guest creation will fail if the feature is supported by host CPU.\nDefaults to require\n+optional", + } +} + +func (Memory) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Memory allows specifying the VirtualMachineInstance memory features.", + "hugepages": "Hugepages allow to use hugepages for the VirtualMachineInstance instead of regular memory.\n+optional", + "guest": "Guest allows to specifying the amount of memory which is visible inside the Guest OS.\nThe Guest must lie between Requests and Limits from the resources section.\nDefaults to the requested memory in the resources section if not specified.\n+ optional", + } +} + +func (Hugepages) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Hugepages allow to use hugepages for the VirtualMachineInstance instead of regular memory.", + "pageSize": "PageSize specifies the hugepage size, for x86_64 architecture valid values are 1Gi and 2Mi.", + } +} + +func (Machine) SwaggerDoc() map[string]string { + return map[string]string{ + "type": "QEMU machine type is the actual chipset of the VirtualMachineInstance.\n+optional", + } +} + +func (Firmware) SwaggerDoc() map[string]string { + return map[string]string{ + "uuid": "UUID reported by the vmi bios.\nDefaults to a random generated uid.", + "bootloader": "Settings to control the bootloader that is used.\n+optional", + "serial": "The system-serial-number in SMBIOS", + "kernelBoot": "Settings to set the kernel for booting.\n+optional", + } +} + +func (Devices) SwaggerDoc() map[string]string { + return map[string]string{ + "useVirtioTransitional": "Fall back to legacy virtio 0.9 support if virtio bus is selected on devices.\nThis is helpful for old machines like CentOS6 or RHEL6 which\ndo not understand virtio_non_transitional (virtio 1.0).", + "disableHotplug": "DisableHotplug disabled the ability to hotplug disks.", + "disks": "Disks describes disks, cdroms and luns which are connected to the vmi.", + "watchdog": "Watchdog describes a watchdog device which can be added to the vmi.", + "interfaces": "Interfaces describe network interfaces which are added to the vmi.", + "inputs": "Inputs describe input devices", + "autoattachPodInterface": "Whether to attach a pod network interface. Defaults to true.", + "autoattachGraphicsDevice": "Whether to attach the default graphics device or not.\nVNC will not be available if set to false. Defaults to true.", + "autoattachSerialConsole": "Whether to attach the default serial console or not.\nSerial console access will not be available if set to false. Defaults to true.", + "autoattachMemBalloon": "Whether to attach the Memory balloon device with default period.\nPeriod can be adjusted in virt-config.\nDefaults to true.\n+optional", + "rng": "Whether to have random number generator from host\n+optional", + "blockMultiQueue": "Whether or not to enable virtio multi-queue for block devices.\nDefaults to false.\n+optional", + "networkInterfaceMultiqueue": "If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature for network devices. The number of queues created depends on additional factors of the VirtualMachineInstance, like the number of guest CPUs.\n+optional", + "gpus": "Whether to attach a GPU device to the vmi.\n+optional\n+listType=atomic", + "filesystems": "Filesystems describes filesystem which is connected to the vmi.\n+optional\n+listType=atomic", + "hostDevices": "Whether to attach a host device to the vmi.\n+optional\n+listType=atomic", + "clientPassthrough": "To configure and access client devices such as redirecting USB\n+optional", + "sound": "Whether to emulate a sound device.\n+optional", + "tpm": "Whether to emulate a TPM device.\n+optional", + } +} + +func (ClientPassthroughDevices) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represent a subset of client devices that can be accessed by VMI. At the\nmoment only, USB devices using Usbredir's library and tooling. Another fit\nwould be a smartcard with libcacard.\n\nThe struct is currently empty as there is no immediate request for\nuser-facing APIs. This structure simply turns on USB redirection of\nUsbClientPassthroughMaxNumberOf devices.", + } +} + +func (SoundDevice) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the user's configuration to emulate sound cards in the VMI.", + "name": "User's defined name for this sound device", + "model": "We only support ich9 or ac97.\nIf SoundDevice is not set: No sound card is emulated.\nIf SoundDevice is set but Model is not: ich9\n+optional", + } +} + +func (TPMDevice) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (Input) SwaggerDoc() map[string]string { + return map[string]string{ + "bus": "Bus indicates the bus of input device to emulate.\nSupported values: virtio, usb.", + "type": "Type indicated the type of input device.\nSupported values: tablet.", + "name": "Name is the device name", + } +} + +func (Filesystem) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Name is the device name", + "virtiofs": "Virtiofs is supported", + } +} + +func (FilesystemVirtiofs) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (GPU) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Name of the GPU device as exposed by a device plugin", + "tag": "If specified, the virtual network interface address and its tag will be provided to the guest via config drive\n+optional", + } +} + +func (VGPUOptions) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (VGPUDisplayOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "enabled": "Enabled determines if a display addapter backed by a vGPU should be enabled or disabled on the guest.\nDefaults to true.\n+optional", + "ramFB": "Enables a boot framebuffer, until the guest OS loads a real GPU driver\nDefaults to true.\n+optional", + } +} + +func (HostDevice) SwaggerDoc() map[string]string { + return map[string]string{ + "deviceName": "DeviceName is the resource name of the host device exposed by a device plugin", + "tag": "If specified, the virtual network interface address and its tag will be provided to the guest via config drive\n+optional", + } +} + +func (Disk) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Name is the device name", + "bootOrder": "BootOrder is an integer value > 0, used to determine ordering of boot devices.\nLower values take precedence.\nEach disk or interface that has a boot order must have a unique value.\nDisks without a boot order are not tried if a disk with a boot order exists.\n+optional", + "serial": "Serial provides the ability to specify a serial number for the disk device.\n+optional", + "dedicatedIOThread": "dedicatedIOThread indicates this disk should have an exclusive IO Thread.\nEnabling this implies useIOThreads = true.\nDefaults to false.\n+optional", + "cache": "Cache specifies which kvm disk cache mode should be used.\nSupported values are: CacheNone, CacheWriteThrough.\n+optional", + "io": "IO specifies which QEMU disk IO mode should be used.\nSupported values are: native, default, threads.\n+optional", + "tag": "If specified, disk address and its tag will be provided to the guest via config drive metadata\n+optional", + "blockSize": "If specified, the virtual disk will be presented with the given block sizes.\n+optional", + "shareable": "If specified the disk is made sharable and multiple write from different VMs are permitted\n+optional", + } +} + +func (CustomBlockSize) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CustomBlockSize represents the desired logical and physical block size for a VM disk.", + } +} + +func (BlockSize) SwaggerDoc() map[string]string { + return map[string]string{ + "": "BlockSize provides the option to change the block size presented to the VM for a disk.\nOnly one of its members may be specified.", + } +} + +func (DiskDevice) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the target of a volume to mount.\nOnly one of its members may be specified.", + "disk": "Attach a volume as a disk to the vmi.", + "lun": "Attach a volume as a LUN to the vmi.", + "cdrom": "Attach a volume as a cdrom to the vmi.", + } +} + +func (DiskTarget) SwaggerDoc() map[string]string { + return map[string]string{ + "bus": "Bus indicates the type of disk device to emulate.\nsupported values: virtio, sata, scsi.", + "readonly": "ReadOnly.\nDefaults to false.", + "pciAddress": "If specified, the virtual disk will be placed on the guests pci address with the specified PCI address. For example: 0000:81:01.10\n+optional", + } +} + +func (LaunchSecurity) SwaggerDoc() map[string]string { + return map[string]string{ + "sev": "AMD Secure Encrypted Virtualization (SEV).", + } +} + +func (SEV) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (LunTarget) SwaggerDoc() map[string]string { + return map[string]string{ + "bus": "Bus indicates the type of disk device to emulate.\nsupported values: virtio, sata, scsi.", + "readonly": "ReadOnly.\nDefaults to false.", + } +} + +func (CDRomTarget) SwaggerDoc() map[string]string { + return map[string]string{ + "bus": "Bus indicates the type of disk device to emulate.\nsupported values: virtio, sata, scsi.", + "readonly": "ReadOnly.\nDefaults to true.", + "tray": "Tray indicates if the tray of the device is open or closed.\nAllowed values are \"open\" and \"closed\".\nDefaults to closed.\n+optional", + } +} + +func (Volume) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Volume represents a named volume in a vmi.", + "name": "Volume's name.\nMust be a DNS_LABEL and unique within the vmi.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + } +} + +func (VolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the source of a volume to mount.\nOnly one of its members may be specified.", + "hostDisk": "HostDisk represents a disk created on the cluster level\n+optional", + "persistentVolumeClaim": "PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace.\nDirectly attached to the vmi via qemu.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims\n+optional", + "cloudInitNoCloud": "CloudInitNoCloud represents a cloud-init NoCloud user-data source.\nThe NoCloud data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest.\nMore info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html\n+optional", + "cloudInitConfigDrive": "CloudInitConfigDrive represents a cloud-init Config Drive user-data source.\nThe Config Drive data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest.\nMore info: https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html\n+optional", + "sysprep": "Represents a Sysprep volume source.\n+optional", + "containerDisk": "ContainerDisk references a docker image, embedding a qcow or raw disk.\nMore info: https://kubevirt.gitbooks.io/user-guide/registry-disk.html\n+optional", + "ephemeral": "Ephemeral is a special volume source that \"wraps\" specified source and provides copy-on-write image on top of it.\n+optional", + "emptyDisk": "EmptyDisk represents a temporary disk which shares the vmis lifecycle.\nMore info: https://kubevirt.gitbooks.io/user-guide/disks-and-volumes.html\n+optional", + "dataVolume": "DataVolume represents the dynamic creation a PVC for this volume as well as\nthe process of populating that PVC with a disk image.\n+optional", + "configMap": "ConfigMapSource represents a reference to a ConfigMap in the same namespace.\nMore info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/\n+optional", + "secret": "SecretVolumeSource represents a reference to a secret data in the same namespace.\nMore info: https://kubernetes.io/docs/concepts/configuration/secret/\n+optional", + "downwardAPI": "DownwardAPI represents downward API about the pod that should populate this volume\n+optional", + "serviceAccount": "ServiceAccountVolumeSource represents a reference to a service account.\nThere can only be one volume of this type!\nMore info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/\n+optional", + "downwardMetrics": "DownwardMetrics adds a very small disk to VMIs which contains a limited view of host and guest\nmetrics. The disk content is compatible with vhostmd (https://github.com/vhostmd/vhostmd) and vm-dump-metrics.", + "memoryDump": "MemoryDump is attached to the virt launcher and is populated with a memory dump of the vmi", + } +} + +func (HotplugVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "HotplugVolumeSource Represents the source of a volume to mount which are capable\nof being hotplugged on a live running VMI.\nOnly one of its members may be specified.", + "persistentVolumeClaim": "PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace.\nDirectly attached to the vmi via qemu.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims\n+optional", + "dataVolume": "DataVolume represents the dynamic creation a PVC for this volume as well as\nthe process of populating that PVC with a disk image.\n+optional", + } +} + +func (DataVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Name represents the name of the DataVolume in the same namespace", + "hotpluggable": "Hotpluggable indicates whether the volume can be hotplugged and hotunplugged.\n+optional", + } +} + +func (PersistentVolumeClaimVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace.\nDirectly attached to the vmi via qemu.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "hotpluggable": "Hotpluggable indicates whether the volume can be hotplugged and hotunplugged.\n+optional", + } +} + +func (MemoryDumpVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (EphemeralVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "persistentVolumeClaim": "PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace.\nDirectly attached to the vmi via qemu.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims\n+optional", + } +} + +func (EmptyDiskSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "EmptyDisk represents a temporary disk which shares the vmis lifecycle.", + "capacity": "Capacity of the sparse disk.", + } +} + +func (ContainerDiskSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents a docker image with an embedded disk.", + "image": "Image is the name of the image with the embedded disk.", + "imagePullSecret": "ImagePullSecret is the name of the Docker registry secret required to pull the image. The secret must already exist.", + "path": "Path defines the path to disk file in the container", + "imagePullPolicy": "Image pull policy.\nOne of Always, Never, IfNotPresent.\nDefaults to Always if :latest tag is specified, or IfNotPresent otherwise.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/containers/images#updating-images\n+optional", + } +} + +func (ClockOffset) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Exactly one of its members must be set.", + "utc": "UTC sets the guest clock to UTC on each boot. If an offset is specified,\nguest changes to the clock will be kept during reboots and are not reset.", + "timezone": "Timezone sets the guest clock to the specified timezone.\nZone name follows the TZ environment variable format (e.g. 'America/New_York').", + } +} + +func (ClockOffsetUTC) SwaggerDoc() map[string]string { + return map[string]string{ + "": "UTC sets the guest clock to UTC on each boot.", + "offsetSeconds": "OffsetSeconds specifies an offset in seconds, relative to UTC. If set,\nguest changes to the clock will be kept during reboots and not reset.", + } +} + +func (Clock) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the clock and timers of a vmi.\n+kubebuilder:pruning:PreserveUnknownFields", + "timer": "Timer specifies whih timers are attached to the vmi.\n+optional", + } +} + +func (Timer) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents all available timers in a vmi.", + "hpet": "HPET (High Precision Event Timer) - multiple timers with periodic interrupts.", + "kvm": "KVM \t(KVM clock) - lets guests read the host’s wall clock time (paravirtualized). For linux guests.", + "pit": "PIT (Programmable Interval Timer) - a timer with periodic interrupts.", + "rtc": "RTC (Real Time Clock) - a continuously running timer with periodic interrupts.", + "hyperv": "Hyperv (Hypervclock) - lets guests read the host’s wall clock time (paravirtualized). For windows guests.", + } +} + +func (RTCTimer) SwaggerDoc() map[string]string { + return map[string]string{ + "tickPolicy": "TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest.\nOne of \"delay\", \"catchup\".", + "present": "Enabled set to false makes sure that the machine type or a preset can't add the timer.\nDefaults to true.\n+optional", + "track": "Track the guest or the wall clock.", + } +} + +func (HPETTimer) SwaggerDoc() map[string]string { + return map[string]string{ + "tickPolicy": "TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest.\nOne of \"delay\", \"catchup\", \"merge\", \"discard\".", + "present": "Enabled set to false makes sure that the machine type or a preset can't add the timer.\nDefaults to true.\n+optional", + } +} + +func (PITTimer) SwaggerDoc() map[string]string { + return map[string]string{ + "tickPolicy": "TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest.\nOne of \"delay\", \"catchup\", \"discard\".", + "present": "Enabled set to false makes sure that the machine type or a preset can't add the timer.\nDefaults to true.\n+optional", + } +} + +func (KVMTimer) SwaggerDoc() map[string]string { + return map[string]string{ + "present": "Enabled set to false makes sure that the machine type or a preset can't add the timer.\nDefaults to true.\n+optional", + } +} + +func (HypervTimer) SwaggerDoc() map[string]string { + return map[string]string{ + "present": "Enabled set to false makes sure that the machine type or a preset can't add the timer.\nDefaults to true.\n+optional", + } +} + +func (Features) SwaggerDoc() map[string]string { + return map[string]string{ + "acpi": "ACPI enables/disables ACPI inside the guest.\nDefaults to enabled.\n+optional", + "apic": "Defaults to the machine type setting.\n+optional", + "hyperv": "Defaults to the machine type setting.\n+optional", + "smm": "SMM enables/disables System Management Mode.\nTSEG not yet implemented.\n+optional", + "kvm": "Configure how KVM presence is exposed to the guest.\n+optional", + "pvspinlock": "Notify the guest that the host supports paravirtual spinlocks.\nFor older kernels this feature should be explicitly disabled.\n+optional", + } +} + +func (SyNICTimer) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (FeatureState) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents if a feature is enabled or disabled.", + "enabled": "Enabled determines if the feature should be enabled or disabled on the guest.\nDefaults to true.\n+optional", + } +} + +func (FeatureAPIC) SwaggerDoc() map[string]string { + return map[string]string{ + "enabled": "Enabled determines if the feature should be enabled or disabled on the guest.\nDefaults to true.\n+optional", + "endOfInterrupt": "EndOfInterrupt enables the end of interrupt notification in the guest.\nDefaults to false.\n+optional", + } +} + +func (FeatureSpinlocks) SwaggerDoc() map[string]string { + return map[string]string{ + "enabled": "Enabled determines if the feature should be enabled or disabled on the guest.\nDefaults to true.\n+optional", + "spinlocks": "Retries indicates the number of retries.\nMust be a value greater or equal 4096.\nDefaults to 4096.\n+optional", + } +} + +func (FeatureVendorID) SwaggerDoc() map[string]string { + return map[string]string{ + "enabled": "Enabled determines if the feature should be enabled or disabled on the guest.\nDefaults to true.\n+optional", + "vendorid": "VendorID sets the hypervisor vendor id, visible to the vmi.\nString up to twelve characters.", + } +} + +func (FeatureHyperv) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Hyperv specific features.", + "relaxed": "Relaxed instructs the guest OS to disable watchdog timeouts.\nDefaults to the machine type setting.\n+optional", + "vapic": "VAPIC improves the paravirtualized handling of interrupts.\nDefaults to the machine type setting.\n+optional", + "spinlocks": "Spinlocks allows to configure the spinlock retry attempts.\n+optional", + "vpindex": "VPIndex enables the Virtual Processor Index to help windows identifying virtual processors.\nDefaults to the machine type setting.\n+optional", + "runtime": "Runtime improves the time accounting to improve scheduling in the guest.\nDefaults to the machine type setting.\n+optional", + "synic": "SyNIC enables the Synthetic Interrupt Controller.\nDefaults to the machine type setting.\n+optional", + "synictimer": "SyNICTimer enables Synthetic Interrupt Controller Timers, reducing CPU load.\nDefaults to the machine type setting.\n+optional", + "reset": "Reset enables Hyperv reboot/reset for the vmi. Requires synic.\nDefaults to the machine type setting.\n+optional", + "vendorid": "VendorID allows setting the hypervisor vendor id.\nDefaults to the machine type setting.\n+optional", + "frequencies": "Frequencies improves the TSC clock source handling for Hyper-V on KVM.\nDefaults to the machine type setting.\n+optional", + "reenlightenment": "Reenlightenment enables the notifications on TSC frequency changes.\nDefaults to the machine type setting.\n+optional", + "tlbflush": "TLBFlush improves performances in overcommited environments. Requires vpindex.\nDefaults to the machine type setting.\n+optional", + "ipi": "IPI improves performances in overcommited environments. Requires vpindex.\nDefaults to the machine type setting.\n+optional", + "evmcs": "EVMCS Speeds up L2 vmexits, but disables other virtualization features. Requires vapic.\nDefaults to the machine type setting.\n+optional", + } +} + +func (FeatureKVM) SwaggerDoc() map[string]string { + return map[string]string{ + "hidden": "Hide the KVM hypervisor from standard MSR based discovery.\nDefaults to false", + } +} + +func (Watchdog) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Named watchdog device.", + "name": "Name of the watchdog.", + } +} + +func (WatchdogDevice) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Hardware watchdog device.\nExactly one of its members must be set.", + "i6300esb": "i6300esb watchdog device.\n+optional", + } +} + +func (I6300ESBWatchdog) SwaggerDoc() map[string]string { + return map[string]string{ + "": "i6300esb watchdog device.", + "action": "The action to take. Valid values are poweroff, reset, shutdown.\nDefaults to reset.", + } +} + +func (Interface) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Logical name of the interface as well as a reference to the associated networks.\nMust match the Name of a Network.", + "model": "Interface model.\nOne of: e1000, e1000e, ne2k_pci, pcnet, rtl8139, virtio.\nDefaults to virtio.", + "ports": "List of ports to be forwarded to the virtual machine.", + "macAddress": "Interface MAC address. For example: de:ad:00:00:be:af or DE-AD-00-00-BE-AF.", + "bootOrder": "BootOrder is an integer value > 0, used to determine ordering of boot devices.\nLower values take precedence.\nEach interface or disk that has a boot order must have a unique value.\nInterfaces without a boot order are not tried.\n+optional", + "pciAddress": "If specified, the virtual network interface will be placed on the guests pci address with the specified PCI address. For example: 0000:81:01.10\n+optional", + "dhcpOptions": "If specified the network interface will pass additional DHCP options to the VMI\n+optional", + "tag": "If specified, the virtual network interface address and its tag will be provided to the guest via config drive\n+optional", + } +} + +func (DHCPOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Extra DHCP options to use in the interface.", + "bootFileName": "If specified will pass option 67 to interface's DHCP server\n+optional", + "tftpServerName": "If specified will pass option 66 to interface's DHCP server\n+optional", + "ntpServers": "If specified will pass the configured NTP server to the VM via DHCP option 042.\n+optional", + "privateOptions": "If specified will pass extra DHCP options for private use, range: 224-254\n+optional", + } +} + +func (DHCPPrivateOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DHCPExtraOptions defines Extra DHCP options for a VM.", + "option": "Option is an Integer value from 224-254\nRequired.", + "value": "Value is a String value for the Option provided\nRequired.", + } +} + +func (InterfaceBindingMethod) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the method which will be used to connect the interface to the guest.\nOnly one of its members may be specified.", + } +} + +func (InterfaceBridge) SwaggerDoc() map[string]string { + return map[string]string{ + "": "InterfaceBridge connects to a given network via a linux bridge.", + } +} + +func (InterfaceSlirp) SwaggerDoc() map[string]string { + return map[string]string{ + "": "InterfaceSlirp connects to a given network using QEMU user networking mode.", + } +} + +func (InterfaceMasquerade) SwaggerDoc() map[string]string { + return map[string]string{ + "": "InterfaceMasquerade connects to a given network using netfilter rules to nat the traffic.", + } +} + +func (InterfaceSRIOV) SwaggerDoc() map[string]string { + return map[string]string{ + "": "InterfaceSRIOV connects to a given network by passing-through an SR-IOV PCI device via vfio.", + } +} + +func (InterfaceMacvtap) SwaggerDoc() map[string]string { + return map[string]string{ + "": "InterfaceMacvtap connects to a given network by extending the Kubernetes node's L2 networks via a macvtap interface.", + } +} + +func (Port) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Port represents a port to expose from the virtual machine.\nDefault protocol TCP.\nThe port field is mandatory", + "name": "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each\nnamed port in a pod must have a unique name. Name for the port that can be\nreferred to by services.\n+optional", + "protocol": "Protocol for port. Must be UDP or TCP.\nDefaults to \"TCP\".\n+optional", + "port": "Number of port to expose for the virtual machine.\nThis must be a valid port number, 0 < x < 65536.", + } +} + +func (AccessCredentialSecretSource) SwaggerDoc() map[string]string { + return map[string]string{ + "secretName": "SecretName represents the name of the secret in the VMI's namespace", + } +} + +func (ConfigDriveSSHPublicKeyAccessCredentialPropagation) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (AuthorizedKeysFile) SwaggerDoc() map[string]string { + return map[string]string{ + "": "AuthorizedKeysFile represents a path within the guest\nthat ssh public keys should be propagated to", + "filePath": "FilePath represents the place on the guest that the authorized_keys\nfile should be writen to. This is expected to be a full path including\nboth the base directory and file name.", + } +} + +func (QemuGuestAgentUserPasswordAccessCredentialPropagation) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (QemuGuestAgentSSHPublicKeyAccessCredentialPropagation) SwaggerDoc() map[string]string { + return map[string]string{ + "users": "Users represents a list of guest users that should have the ssh public keys\nadded to their authorized_keys file.\n+listType=set", + } +} + +func (SSHPublicKeyAccessCredentialSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "SSHPublicKeyAccessCredentialSource represents where to retrieve the ssh key\ncredentials\nOnly one of its members may be specified.", + "secret": "Secret means that the access credential is pulled from a kubernetes secret\n+optional", + } +} + +func (SSHPublicKeyAccessCredentialPropagationMethod) SwaggerDoc() map[string]string { + return map[string]string{ + "": "SSHPublicKeyAccessCredentialPropagationMethod represents the method used to\ninject a ssh public key into the vm guest.\nOnly one of its members may be specified.", + "configDrive": "ConfigDrivePropagation means that the ssh public keys are injected\ninto the VM using metadata using the configDrive cloud-init provider\n+optional", + "qemuGuestAgent": "QemuGuestAgentAccessCredentailPropagation means ssh public keys are\ndynamically injected into the vm at runtime via the qemu guest agent.\nThis feature requires the qemu guest agent to be running within the guest.\n+optional", + } +} + +func (SSHPublicKeyAccessCredential) SwaggerDoc() map[string]string { + return map[string]string{ + "": "SSHPublicKeyAccessCredential represents a source and propagation method for\ninjecting ssh public keys into a vm guest", + "source": "Source represents where the public keys are pulled from", + "propagationMethod": "PropagationMethod represents how the public key is injected into the vm guest.", + } +} + +func (UserPasswordAccessCredentialSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "UserPasswordAccessCredentialSource represents where to retrieve the user password\ncredentials\nOnly one of its members may be specified.", + "secret": "Secret means that the access credential is pulled from a kubernetes secret\n+optional", + } +} + +func (UserPasswordAccessCredentialPropagationMethod) SwaggerDoc() map[string]string { + return map[string]string{ + "": "UserPasswordAccessCredentialPropagationMethod represents the method used to\ninject a user passwords into the vm guest.\nOnly one of its members may be specified.", + "qemuGuestAgent": "QemuGuestAgentAccessCredentailPropagation means passwords are\ndynamically injected into the vm at runtime via the qemu guest agent.\nThis feature requires the qemu guest agent to be running within the guest.\n+optional", + } +} + +func (UserPasswordAccessCredential) SwaggerDoc() map[string]string { + return map[string]string{ + "": "UserPasswordAccessCredential represents a source and propagation method for\ninjecting user passwords into a vm guest\nOnly one of its members may be specified.", + "source": "Source represents where the user passwords are pulled from", + "propagationMethod": "propagationMethod represents how the user passwords are injected into the vm guest.", + } +} + +func (AccessCredential) SwaggerDoc() map[string]string { + return map[string]string{ + "": "AccessCredential represents a credential source that can be used to\nauthorize remote access to the vm guest\nOnly one of its members may be specified.", + "sshPublicKey": "SSHPublicKey represents the source and method of applying a ssh public\nkey into a guest virtual machine.\n+optional", + "userPassword": "UserPassword represents the source and method for applying a guest user's\npassword\n+optional", + } +} + +func (Network) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Network represents a network type and a resource that should be connected to the vm.", + "name": "Network name.\nMust be a DNS_LABEL and unique within the vm.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + } +} + +func (NetworkSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the source resource that will be connected to the vm.\nOnly one of its members may be specified.", + } +} + +func (PodNetwork) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the stock pod network interface.", + "vmNetworkCIDR": "CIDR for vm network.\nDefault 10.0.2.0/24 if not specified.", + "vmIPv6NetworkCIDR": "IPv6 CIDR for the vm network.\nDefaults to fd10:0:2::/120 if not specified.", + } +} + +func (Rng) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Rng represents the random device passed from host", + } +} + +func (MultusNetwork) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Represents the multus cni network.", + "networkName": "References to a NetworkAttachmentDefinition CRD object. Format:\n, /. If namespace is not\nspecified, VMI namespace is assumed.", + "default": "Select the default network and add it to the\nmultus-cni.io/default-network annotation.", + } +} diff --git a/vendor/kubevirt.io/api/core/v1/types.go b/vendor/kubevirt.io/api/core/v1/types.go new file mode 100644 index 00000000..bc16c262 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/types.go @@ -0,0 +1,2315 @@ +/* + * This file is part of the KubeVirt project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2017 Red Hat, Inc. + * + */ + +package v1 + +/* + ATTENTION: Rerun code generators when comments on structs or fields are modified. +*/ + +import ( + "encoding/json" + "fmt" + + k8sv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + + cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" +) + +const DefaultGracePeriodSeconds int64 = 30 + +// VirtualMachineInstance is *the* VirtualMachineInstance Definition. It represents a virtual machine in the runtime environment of kubernetes. +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type VirtualMachineInstance struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + // VirtualMachineInstance Spec contains the VirtualMachineInstance specification. + Spec VirtualMachineInstanceSpec `json:"spec" valid:"required"` + // Status is the high level overview of how the VirtualMachineInstance is doing. It contains information available to controllers and users. + Status VirtualMachineInstanceStatus `json:"status,omitempty"` +} + +func (v *VirtualMachineInstance) MarshalBinary() (data []byte, err error) { + return json.Marshal(*v) +} + +func (v *VirtualMachineInstance) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, v) +} + +// VirtualMachineInstanceList is a list of VirtualMachines +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstanceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachineInstance `json:"items"` +} + +type EvictionStrategy string + +type StartStrategy string + +const ( + StartStrategyPaused StartStrategy = "Paused" +) + +// VirtualMachineInstanceSpec is a description of a VirtualMachineInstance. +type VirtualMachineInstanceSpec struct { + + // If specified, indicates the pod's priority. + // If not specified, the pod priority will be default or zero if there is no + // default. + // +optional + PriorityClassName string `json:"priorityClassName,omitempty"` + + // Specification of the desired behavior of the VirtualMachineInstance on the host. + Domain DomainSpec `json:"domain"` + // NodeSelector is a selector which must be true for the vmi to fit on a node. + // Selector which must match a node's labels for the vmi to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + // If affinity is specifies, obey all the affinity rules + Affinity *k8sv1.Affinity `json:"affinity,omitempty"` + // If specified, the VMI will be dispatched by specified scheduler. + // If not specified, the VMI will be dispatched by default scheduler. + // +optional + SchedulerName string `json:"schedulerName,omitempty"` + // If toleration is specified, obey all the toleration rules. + Tolerations []k8sv1.Toleration `json:"tolerations,omitempty"` + + // EvictionStrategy can be set to "LiveMigrate" if the VirtualMachineInstance should be + // migrated instead of shut-off in case of a node drain. + // + // +optional + EvictionStrategy *EvictionStrategy `json:"evictionStrategy,omitempty"` + // StartStrategy can be set to "Paused" if Virtual Machine should be started in paused state. + // + // +optional + StartStrategy *StartStrategy `json:"startStrategy,omitempty"` + // Grace period observed after signalling a VirtualMachineInstance to stop after which the VirtualMachineInstance is force terminated. + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` + // List of volumes that can be mounted by disks belonging to the vmi. + Volumes []Volume `json:"volumes,omitempty"` + // Periodic probe of VirtualMachineInstance liveness. + // VirtualmachineInstances will be stopped if the probe fails. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + // +optional + LivenessProbe *Probe `json:"livenessProbe,omitempty"` + // Periodic probe of VirtualMachineInstance service readiness. + // VirtualmachineInstances will be removed from service endpoints if the probe fails. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + // +optional + ReadinessProbe *Probe `json:"readinessProbe,omitempty"` + // Specifies the hostname of the vmi + // If not specified, the hostname will be set to the name of the vmi, if dhcp or cloud-init is configured properly. + // +optional + Hostname string `json:"hostname,omitempty"` + // If specified, the fully qualified vmi hostname will be "...svc.". + // If not specified, the vmi will not have a domainname at all. The DNS entry will resolve to the vmi, + // no matter if the vmi itself can pick up a hostname. + // +optional + Subdomain string `json:"subdomain,omitempty"` + // List of networks that can be attached to a vm's virtual interface. + Networks []Network `json:"networks,omitempty"` + // Set DNS policy for the pod. + // Defaults to "ClusterFirst". + // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. + // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. + // To have DNS options set along with hostNetwork, you have to specify DNS policy + // explicitly to 'ClusterFirstWithHostNet'. + // +optional + DNSPolicy k8sv1.DNSPolicy `json:"dnsPolicy,omitempty" protobuf:"bytes,6,opt,name=dnsPolicy,casttype=DNSPolicy"` + // Specifies the DNS parameters of a pod. + // Parameters specified here will be merged to the generated DNS + // configuration based on DNSPolicy. + // +optional + DNSConfig *k8sv1.PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` + // Specifies a set of public keys to inject into the vm guest + // +listType=atomic + // +optional + AccessCredentials []AccessCredential `json:"accessCredentials,omitempty"` +} + +func (vmiSpec *VirtualMachineInstanceSpec) UnmarshalJSON(data []byte) error { + type VMISpecAlias VirtualMachineInstanceSpec + var vmiSpecAlias VMISpecAlias + + if err := json.Unmarshal(data, &vmiSpecAlias); err != nil { + return err + } + + if vmiSpecAlias.DNSConfig != nil { + for i, ns := range vmiSpecAlias.DNSConfig.Nameservers { + if sanitizedIP, err := sanitizeIP(ns); err == nil { + vmiSpecAlias.DNSConfig.Nameservers[i] = sanitizedIP + } + } + } + + *vmiSpec = VirtualMachineInstanceSpec(vmiSpecAlias) + return nil +} + +// VirtualMachineInstancePhaseTransitionTimestamp gives a timestamp in relation to when a phase is set on a vmi +type VirtualMachineInstancePhaseTransitionTimestamp struct { + // Phase is the status of the VirtualMachineInstance in kubernetes world. It is not the VirtualMachineInstance status, but partially correlates to it. + Phase VirtualMachineInstancePhase `json:"phase,omitempty"` + // PhaseTransitionTimestamp is the timestamp of when the phase change occurred + PhaseTransitionTimestamp metav1.Time `json:"phaseTransitionTimestamp,omitempty"` +} + +type TopologyHints struct { + TSCFrequency *int64 `json:"tscFrequency,omitempty"` +} + +// VirtualMachineInstanceStatus represents information about the status of a VirtualMachineInstance. Status may trail the actual +// state of a system. +type VirtualMachineInstanceStatus struct { + // NodeName is the name where the VirtualMachineInstance is currently running. + NodeName string `json:"nodeName,omitempty"` + // A brief CamelCase message indicating details about why the VMI is in this state. e.g. 'NodeUnresponsive' + // +optional + Reason string `json:"reason,omitempty"` + // Conditions are specific points in VirtualMachineInstance's pod runtime. + Conditions []VirtualMachineInstanceCondition `json:"conditions,omitempty"` + // Phase is the status of the VirtualMachineInstance in kubernetes world. It is not the VirtualMachineInstance status, but partially correlates to it. + Phase VirtualMachineInstancePhase `json:"phase,omitempty"` + // PhaseTransitionTimestamp is the timestamp of when the last phase change occurred + // +listType=atomic + // +optional + PhaseTransitionTimestamps []VirtualMachineInstancePhaseTransitionTimestamp `json:"phaseTransitionTimestamps,omitempty"` + // Interfaces represent the details of available network interfaces. + Interfaces []VirtualMachineInstanceNetworkInterface `json:"interfaces,omitempty"` + // Guest OS Information + GuestOSInfo VirtualMachineInstanceGuestOSInfo `json:"guestOSInfo,omitempty"` + // Represents the status of a live migration + MigrationState *VirtualMachineInstanceMigrationState `json:"migrationState,omitempty"` + // Represents the method using which the vmi can be migrated: live migration or block migration + MigrationMethod VirtualMachineInstanceMigrationMethod `json:"migrationMethod,omitempty"` + // This represents the migration transport + MigrationTransport VirtualMachineInstanceMigrationTransport `json:"migrationTransport,omitempty"` + // The Quality of Service (QOS) classification assigned to the virtual machine instance based on resource requirements + // See PodQOSClass type for available QOS classes + // More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md + // +optional + QOSClass *k8sv1.PodQOSClass `json:"qosClass,omitempty"` + + // LauncherContainerImageVersion indicates what container image is currently active for the vmi. + LauncherContainerImageVersion string `json:"launcherContainerImageVersion,omitempty"` + + // EvacuationNodeName is used to track the eviction process of a VMI. It stores the name of the node that we want + // to evacuate. It is meant to be used by KubeVirt core components only and can't be set or modified by users. + // +optional + EvacuationNodeName string `json:"evacuationNodeName,omitempty"` + + // ActivePods is a mapping of pod UID to node name. + // It is possible for multiple pods to be running for a single VMI during migration. + ActivePods map[types.UID]string `json:"activePods,omitempty"` + + // VolumeStatus contains the statuses of all the volumes + // +optional + // +listType=atomic + VolumeStatus []VolumeStatus `json:"volumeStatus,omitempty"` + + // FSFreezeStatus is the state of the fs of the guest + // it can be either frozen or thawed + // +optional + FSFreezeStatus string `json:"fsFreezeStatus,omitempty"` + + // +optional + TopologyHints *TopologyHints `json:"topologyHints,omitempty"` + + //VirtualMachineRevisionName is used to get the vm revision of the vmi when doing + // an online vm snapshot + // +optional + VirtualMachineRevisionName string `json:"virtualMachineRevisionName,omitempty"` + + // RuntimeUser is used to determine what user will be used in launcher + // +optional + RuntimeUser uint64 `json:"runtimeUser"` +} + +// PersistentVolumeClaimInfo contains the relavant information virt-handler needs cached about a PVC +type PersistentVolumeClaimInfo struct { + // AccessModes contains the desired access modes the volume should have. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + // +listType=atomic + // +optional + AccessModes []k8sv1.PersistentVolumeAccessMode `json:"accessModes,omitempty"` + + // VolumeMode defines what type of volume is required by the claim. + // Value of Filesystem is implied when not included in claim spec. + // +optional + VolumeMode *k8sv1.PersistentVolumeMode `json:"volumeMode,omitempty"` + + // Capacity represents the capacity set on the corresponding PVC status + // +optional + Capacity k8sv1.ResourceList `json:"capacity,omitempty"` + + // Requests represents the resources requested by the corresponding PVC spec + // +optional + Requests k8sv1.ResourceList `json:"requests,omitempty"` + + // Preallocated indicates if the PVC's storage is preallocated or not + // +optional + Preallocated bool `json:"preallocated,omitempty"` + + // Percentage of filesystem's size to be reserved when resizing the PVC + // +optional + FilesystemOverhead *cdiv1.Percent `json:"filesystemOverhead,omitempty"` +} + +// VolumeStatus represents information about the status of volumes attached to the VirtualMachineInstance. +type VolumeStatus struct { + // Name is the name of the volume + Name string `json:"name"` + // Target is the target name used when adding the volume to the VM, eg: vda + Target string `json:"target"` + // Phase is the phase + Phase VolumePhase `json:"phase,omitempty"` + // Reason is a brief description of why we are in the current hotplug volume phase + Reason string `json:"reason,omitempty"` + // Message is a detailed message about the current hotplug volume phase + Message string `json:"message,omitempty"` + // PersistentVolumeClaimInfo is information about the PVC that handler requires during start flow + PersistentVolumeClaimInfo *PersistentVolumeClaimInfo `json:"persistentVolumeClaimInfo,omitempty"` + // If the volume is hotplug, this will contain the hotplug status. + HotplugVolume *HotplugVolumeStatus `json:"hotplugVolume,omitempty"` + // Represents the size of the volume + Size int64 `json:"size,omitempty"` + // If the volume is memorydump volume, this will contain the memorydump info. + MemoryDumpVolume *DomainMemoryDumpInfo `json:"memoryDumpVolume,omitempty"` +} + +// DomainMemoryDumpInfo represents the memory dump information +type DomainMemoryDumpInfo struct { + // StartTimestamp is the time when the memory dump started + StartTimestamp *metav1.Time `json:"startTimestamp,omitempty"` + // EndTimestamp is the time when the memory dump completed + EndTimestamp *metav1.Time `json:"endTimestamp,omitempty"` + // ClaimName is the name of the pvc the memory was dumped to + ClaimName string `json:"claimName,omitempty"` + // TargetFileName is the name of the memory dump output + TargetFileName string `json:"targetFileName,omitempty"` +} + +// HotplugVolumeStatus represents the hotplug status of the volume +type HotplugVolumeStatus struct { + // AttachPodName is the name of the pod used to attach the volume to the node. + AttachPodName string `json:"attachPodName,omitempty"` + // AttachPodUID is the UID of the pod used to attach the volume to the node. + AttachPodUID types.UID `json:"attachPodUID,omitempty"` +} + +// VolumePhase indicates the current phase of the hotplug process. +type VolumePhase string + +const ( + // VolumePending means the Volume is pending and cannot be attached to the node yet. + VolumePending VolumePhase = "Pending" + // VolumeBound means the Volume is bound and can be attach to the node. + VolumeBound VolumePhase = "Bound" + // HotplugVolumeAttachedToNode means the volume has been attached to the node. + HotplugVolumeAttachedToNode VolumePhase = "AttachedToNode" + // HotplugVolumeMounted means the volume has been attached to the node and is mounted to the virt-launcher pod. + HotplugVolumeMounted VolumePhase = "MountedToPod" + // VolumeReady means the volume is ready to be used by the VirtualMachineInstance. + VolumeReady VolumePhase = "Ready" + // HotplugVolumeDetaching means the volume is being detached from the node, and the attachment pod is being removed. + HotplugVolumeDetaching VolumePhase = "Detaching" + // HotplugVolumeUnMounted means the volume has been unmounted from the virt-launcer pod. + HotplugVolumeUnMounted VolumePhase = "UnMountedFromPod" + // MemoryDumpVolumeCompleted means that the requested memory dump was completed and the dump is ready in the volume + MemoryDumpVolumeCompleted VolumePhase = "MemoryDumpCompleted" + // MemoryDumpVolumeInProgress means that the volume for the memory dump was attached, and now the command is being triggered + MemoryDumpVolumeInProgress VolumePhase = "MemoryDumpInProgress" + // MemoryDumpVolumeInProgress means that the volume for the memory dump was attached, and now the command is being triggered + MemoryDumpVolumeFailed VolumePhase = "MemoryDumpFailed" +) + +func (v *VirtualMachineInstance) IsScheduling() bool { + return v.Status.Phase == Scheduling +} + +func (v *VirtualMachineInstance) IsScheduled() bool { + return v.Status.Phase == Scheduled +} + +func (v *VirtualMachineInstance) IsRunning() bool { + return v.Status.Phase == Running +} + +func (v *VirtualMachineInstance) IsMarkedForEviction() bool { + return v.Status.EvacuationNodeName != "" +} + +func (v *VirtualMachineInstance) IsMigratable() bool { + for _, cond := range v.Status.Conditions { + if cond.Type == VirtualMachineInstanceIsMigratable && cond.Status == k8sv1.ConditionTrue { + return true + } + } + return false +} + +func (v *VirtualMachineInstance) IsFinal() bool { + return v.Status.Phase == Failed || v.Status.Phase == Succeeded +} + +func (v *VirtualMachineInstance) IsMarkedForDeletion() bool { + return v.ObjectMeta.DeletionTimestamp != nil +} + +func (v *VirtualMachineInstance) IsUnknown() bool { + return v.Status.Phase == Unknown +} + +func (v *VirtualMachineInstance) IsUnprocessed() bool { + return v.Status.Phase == Pending || v.Status.Phase == VmPhaseUnset +} + +// Checks if CPU pinning has been requested +func (v *VirtualMachineInstance) IsCPUDedicated() bool { + return v.Spec.Domain.CPU != nil && v.Spec.Domain.CPU.DedicatedCPUPlacement +} + +func (v *VirtualMachineInstance) IsBootloaderEFI() bool { + return v.Spec.Domain.Firmware != nil && v.Spec.Domain.Firmware.Bootloader != nil && + v.Spec.Domain.Firmware.Bootloader.EFI != nil +} + +// WantsToHaveQOSGuaranteed checks if cpu and memoyr limits and requests are identical on the VMI. +// This is the indicator that people want a VMI with QOS of guaranteed +func (v *VirtualMachineInstance) WantsToHaveQOSGuaranteed() bool { + resources := v.Spec.Domain.Resources + return !resources.Requests.Memory().IsZero() && resources.Requests.Memory().Cmp(*resources.Limits.Memory()) == 0 && + !resources.Requests.Cpu().IsZero() && resources.Requests.Cpu().Cmp(*resources.Limits.Cpu()) == 0 +} + +// ShouldStartPaused returns true if VMI should be started in paused state +func (v *VirtualMachineInstance) ShouldStartPaused() bool { + return v.Spec.StartStrategy != nil && *v.Spec.StartStrategy == StartStrategyPaused +} + +func (v *VirtualMachineInstance) IsRealtimeEnabled() bool { + return v.Spec.Domain.CPU != nil && v.Spec.Domain.CPU.Realtime != nil +} + +type VirtualMachineInstanceConditionType string + +// These are valid conditions of VMIs. +const ( + // Provisioning means, a VMI depends on DataVolumes which are in Pending/WaitForFirstConsumer status, + // and some actions are taken to provision the PVCs for the DataVolumes + VirtualMachineInstanceProvisioning VirtualMachineInstanceConditionType = "Provisioning" + + // Ready means the VMI is able to service requests and should be added to the + // load balancing pools of all matching services. + VirtualMachineInstanceReady VirtualMachineInstanceConditionType = "Ready" + + // If there happens any error while trying to synchronize the VirtualMachineInstance with the Domain, + // this is reported as false. + VirtualMachineInstanceSynchronized VirtualMachineInstanceConditionType = "Synchronized" + + // If the VMI was paused by the user, this is reported as true. + VirtualMachineInstancePaused VirtualMachineInstanceConditionType = "Paused" + + // Reflects whether the QEMU guest agent is connected through the channel + VirtualMachineInstanceAgentConnected VirtualMachineInstanceConditionType = "AgentConnected" + + // Reflects whether the QEMU guest agent updated access credentials successfully + VirtualMachineInstanceAccessCredentialsSynchronized VirtualMachineInstanceConditionType = "AccessCredentialsSynchronized" + + // Reflects whether the QEMU guest agent is connected through the channel + VirtualMachineInstanceUnsupportedAgent VirtualMachineInstanceConditionType = "AgentVersionNotSupported" + + // Indicates whether the VMI is live migratable + VirtualMachineInstanceIsMigratable VirtualMachineInstanceConditionType = "LiveMigratable" + // Reason means that VMI is not live migratioable because of it's disks collection + VirtualMachineInstanceReasonDisksNotMigratable = "DisksNotLiveMigratable" + // Reason means that VMI is not live migratioable because of it's network interfaces collection + VirtualMachineInstanceReasonInterfaceNotMigratable = "InterfaceNotLiveMigratable" + // Reason means that VMI is not live migratioable because it uses hotplug + VirtualMachineInstanceReasonHotplugNotMigratable = "HotplugNotLiveMigratable" + // Reason means that VMI is not live migratioable because of it's CPU mode + VirtualMachineInstanceReasonCPUModeNotMigratable = "CPUModeLiveMigratable" + // Reason means that VMI is not live migratable because it uses virtiofs + VirtualMachineInstanceReasonVirtIOFSNotMigratable = "VirtIOFSNotLiveMigratable" + // Reason means that VMI is not live migratable because it uses PCI host devices + VirtualMachineInstanceReasonHostDeviceNotMigratable = "HostDeviceNotLiveMigratable" + // Reason means that VMI is not live migratable because it uses Secure Encrypted Virtualization (SEV) + VirtualMachineInstanceReasonSEVNotMigratable = "SEVNotLiveMigratable" +) + +const ( + // PodTerminatingReason indicates on the Ready condition on the VMI if the underlying pod is terminating + PodTerminatingReason = "PodTerminating" + + // PodNotExistsReason indicates on the Ready condition on the VMI if the underlying pod does not exist + PodNotExistsReason = "PodNotExists" + + // PodConditionMissingReason indicates on the Ready condition on the VMI if the underlying pod does not report a Ready condition + PodConditionMissingReason = "PodConditionMissing" + + // GuestNotRunningReason indicates on the Ready condition on the VMI if the underlying guest VM is not running + GuestNotRunningReason = "GuestNotRunning" +) + +type VirtualMachineInstanceMigrationConditionType string + +// These are valid conditions of VMIs. +const ( + // VirtualMachineInstanceMigrationAbortRequested indicates that live migration abort has been requested + VirtualMachineInstanceMigrationAbortRequested VirtualMachineInstanceMigrationConditionType = "migrationAbortRequested" +) + +type VirtualMachineInstanceCondition struct { + Type VirtualMachineInstanceConditionType `json:"type"` + Status k8sv1.ConditionStatus `json:"status"` + // +nullable + LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"` + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +type VirtualMachineInstanceMigrationCondition struct { + Type VirtualMachineInstanceMigrationConditionType `json:"type"` + Status k8sv1.ConditionStatus `json:"status"` + // +nullable + LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"` + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// The migration phase indicates that the job has completed +func (m *VirtualMachineInstanceMigration) IsFinal() bool { + return m.Status.Phase == MigrationFailed || m.Status.Phase == MigrationSucceeded +} + +func (m *VirtualMachineInstanceMigration) IsRunning() bool { + switch m.Status.Phase { + case MigrationFailed, MigrationPending, MigrationPhaseUnset, MigrationSucceeded: + return false + } + return true +} + +// The migration phase indicates that the target pod should have already been created +func (m *VirtualMachineInstanceMigration) TargetIsCreated() bool { + return m.Status.Phase != MigrationPhaseUnset && + m.Status.Phase != MigrationPending +} + +// The migration phase indicates that job has been handed off to the VMI controllers to complete. +func (m *VirtualMachineInstanceMigration) TargetIsHandedOff() bool { + return m.Status.Phase != MigrationPhaseUnset && + m.Status.Phase != MigrationPending && + m.Status.Phase != MigrationScheduling && + m.Status.Phase != MigrationScheduled +} + +type VirtualMachineInstanceNetworkInterface struct { + // IP address of a Virtual Machine interface. It is always the first item of + // IPs + IP string `json:"ipAddress,omitempty"` + // Hardware address of a Virtual Machine interface + MAC string `json:"mac,omitempty"` + // Name of the interface, corresponds to name of the network assigned to the interface + Name string `json:"name,omitempty"` + // List of all IP addresses of a Virtual Machine interface + IPs []string `json:"ipAddresses,omitempty"` + // The interface name inside the Virtual Machine + InterfaceName string `json:"interfaceName,omitempty"` + // Specifies the origin of the interface data collected. values: domain, guest-agent, or both + InfoSource string `json:"infoSource,omitempty"` +} + +type VirtualMachineInstanceGuestOSInfo struct { + // Name of the Guest OS + Name string `json:"name,omitempty"` + // Guest OS Kernel Release + KernelRelease string `json:"kernelRelease,omitempty"` + // Guest OS Version + Version string `json:"version,omitempty"` + // Guest OS Pretty Name + PrettyName string `json:"prettyName,omitempty"` + // Version ID of the Guest OS + VersionID string `json:"versionId,omitempty"` + // Kernel version of the Guest OS + KernelVersion string `json:"kernelVersion,omitempty"` + // Machine type of the Guest OS + Machine string `json:"machine,omitempty"` + // Guest OS Id + ID string `json:"id,omitempty"` +} + +// MigrationConfigSource indicates the source of migration configuration. +// +// +k8s:openapi-gen=true +type MigrationConfigSource string + +// +k8s:openapi-gen=true +type VirtualMachineInstanceMigrationState struct { + // The time the migration action began + // +nullable + StartTimestamp *metav1.Time `json:"startTimestamp,omitempty"` + // The time the migration action ended + // +nullable + EndTimestamp *metav1.Time `json:"endTimestamp,omitempty"` + // The Target Node has seen the Domain Start Event + TargetNodeDomainDetected bool `json:"targetNodeDomainDetected,omitempty"` + // The address of the target node to use for the migration + TargetNodeAddress string `json:"targetNodeAddress,omitempty"` + // The list of ports opened for live migration on the destination node + TargetDirectMigrationNodePorts map[string]int `json:"targetDirectMigrationNodePorts,omitempty"` + // The target node that the VMI is moving to + TargetNode string `json:"targetNode,omitempty"` + // The target pod that the VMI is moving to + TargetPod string `json:"targetPod,omitempty"` + // The UID of the target attachment pod for hotplug volumes + TargetAttachmentPodUID types.UID `json:"targetAttachmentPodUID,omitempty"` + // The source node that the VMI originated on + SourceNode string `json:"sourceNode,omitempty"` + // Indicates the migration completed + Completed bool `json:"completed,omitempty"` + // Indicates that the migration failed + Failed bool `json:"failed,omitempty"` + // Indicates that the migration has been requested to abort + AbortRequested bool `json:"abortRequested,omitempty"` + // Indicates the final status of the live migration abortion + AbortStatus MigrationAbortStatus `json:"abortStatus,omitempty"` + // The VirtualMachineInstanceMigration object associated with this migration + MigrationUID types.UID `json:"migrationUid,omitempty"` + // Lets us know if the vmi is currently running pre or post copy migration + Mode MigrationMode `json:"mode,omitempty"` + // Name of the migration policy. If string is empty, no policy is matched + MigrationPolicyName *string `json:"migrationPolicyName,omitempty"` + // Migration configurations to apply + MigrationConfiguration *MigrationConfiguration `json:"migrationConfiguration,omitempty"` + // If the VMI requires dedicated CPUs, this field will + // hold the dedicated CPU set on the target node + // +listType=atomic + TargetCPUSet []int `json:"targetCPUSet,omitempty"` + // If the VMI requires dedicated CPUs, this field will + // hold the numa topology on the target node + TargetNodeTopology string `json:"targetNodeTopology,omitempty"` +} + +type MigrationAbortStatus string + +const ( + // MigrationAbortSucceeded means that the VirtualMachineInstance live migration has been aborted + MigrationAbortSucceeded MigrationAbortStatus = "Succeeded" + // MigrationAbortFailed means that the vmi live migration has failed to be abort + MigrationAbortFailed MigrationAbortStatus = "Failed" + // MigrationAbortInProgress mean that the vmi live migration is aborting + MigrationAbortInProgress MigrationAbortStatus = "Aborting" +) + +type MigrationMode string + +const ( + // MigrationPreCopy means the VMI migrations that is currently running is in pre copy mode + MigrationPreCopy MigrationMode = "PreCopy" + // MigrationPostCopy means the VMI migrations that is currently running is in post copy mode + MigrationPostCopy MigrationMode = "PostCopy" +) + +type VirtualMachineInstanceMigrationTransport string + +const ( + // MigrationTransportUnix means that the VMI will be migrated using the unix URI + MigrationTransportUnix VirtualMachineInstanceMigrationTransport = "Unix" +) + +type VirtualMachineInstanceMigrationMethod string + +const ( + // BlockMigration means that all VirtualMachineInstance disks should be copied over to the destination host + BlockMigration VirtualMachineInstanceMigrationMethod = "BlockMigration" + // LiveMigration means that VirtualMachineInstance disks will not be copied over to the destination host + LiveMigration VirtualMachineInstanceMigrationMethod = "LiveMigration" +) + +// VirtualMachineInstancePhase is a label for the condition of a VirtualMachineInstance at the current time. +type VirtualMachineInstancePhase string + +// These are the valid statuses of pods. +const ( + //When a VirtualMachineInstance Object is first initialized and no phase, or Pending is present. + VmPhaseUnset VirtualMachineInstancePhase = "" + // Pending means the VirtualMachineInstance has been accepted by the system. + Pending VirtualMachineInstancePhase = "Pending" + // A target Pod exists but is not yet scheduled and in running state. + Scheduling VirtualMachineInstancePhase = "Scheduling" + // A target pod was scheduled and the system saw that Pod in runnig state. + // Here is where the responsibility of virt-controller ends and virt-handler takes over. + Scheduled VirtualMachineInstancePhase = "Scheduled" + // Running means the pod has been bound to a node and the VirtualMachineInstance is started. + Running VirtualMachineInstancePhase = "Running" + // Succeeded means that the VirtualMachineInstance stopped voluntarily, e.g. reacted to SIGTERM or shutdown was invoked from + // inside the VirtualMachineInstance. + Succeeded VirtualMachineInstancePhase = "Succeeded" + // Failed means that the vmi crashed, disappeared unexpectedly or got deleted from the cluster before it was ever started. + Failed VirtualMachineInstancePhase = "Failed" + // Unknown means that for some reason the state of the VirtualMachineInstance could not be obtained, typically due + // to an error in communicating with the host of the VirtualMachineInstance. + Unknown VirtualMachineInstancePhase = "Unknown" +) + +const ( + // AppLabel and AppName labels marks resources that belong to KubeVirt. An optional value + // may indicate which specific KubeVirt component a resource belongs to. + AppLabel string = "kubevirt.io" + AppName string = "name" + // This annotation is used to match virtual machine instances represented as + // libvirt XML domains with their pods. Among other things, the annotation is + // used to detect virtual machines with dead pods. Used on Pod. + DomainAnnotation string = "kubevirt.io/domain" + // Represents the name of the migration job this target pod is associated with + MigrationJobNameAnnotation string = "kubevirt.io/migrationJobName" + ControllerAPILatestVersionObservedAnnotation string = "kubevirt.io/latest-observed-api-version" + ControllerAPIStorageVersionObservedAnnotation string = "kubevirt.io/storage-observed-api-version" + // Used by functional tests to force a VMI to fail the migration internally within launcher + FuncTestForceLauncherMigrationFailureAnnotation string = "kubevirt.io/func-test-force-launcher-migration-failure" + // Used by functional tests to prevent virt launcher from finishing the target pod preparation. + FuncTestBlockLauncherPrepareMigrationTargetAnnotation string = "kubevirt.io/func-test-block-migration-target-preparation" + + // Used by functional tests set custom image on migration target pod + FuncTestMigrationTargetImageOverrideAnnotation string = "kubevirt.io/func-test-migration-target-image-override" + + // Used by functional tests to simulate virt-launcher crash looping + FuncTestLauncherFailFastAnnotation string = "kubevirt.io/func-test-virt-launcher-fail-fast" + // This label is used to match virtual machine instance IDs with pods. + // Similar to kubevirt.io/domain. Used on Pod. + // Internal use only. + CreatedByLabel string = "kubevirt.io/created-by" + // This label is used to indicate that this pod is the target of a migration job. + MigrationJobLabel string = "kubevirt.io/migrationJobUID" + // This label indicates the migration name that a PDB is protecting. + MigrationNameLabel string = "kubevirt.io/migrationName" + // This label describes which cluster node runs the virtual machine + // instance. Needed because with CRDs we can't use field selectors. Used on + // VirtualMachineInstance. + NodeNameLabel string = "kubevirt.io/nodeName" + // This label describes which cluster node runs the target Pod for a Virtual + // Machine Instance migration job. Needed because with CRDs we can't use field + // selectors. Used on VirtualMachineInstance. + MigrationTargetNodeNameLabel string = "kubevirt.io/migrationTargetNodeName" + // This annotation indicates that a migration is the result of an + // automated evacuation + EvacuationMigrationAnnotation string = "kubevirt.io/evacuationMigration" + // This annotation indicates that a migration is the result of an + // automated workload update + WorkloadUpdateMigrationAnnotation string = "kubevirt.io/workloadUpdateMigration" + // This label declares whether a particular node is available for + // scheduling virtual machine instances on it. Used on Node. + NodeSchedulable string = "kubevirt.io/schedulable" + // This annotation is regularly updated by virt-handler to help determine + // if a particular node is alive and hence should be available for new + // virtual machine instance scheduling. Used on Node. + VirtHandlerHeartbeat string = "kubevirt.io/heartbeat" + // This label indicates what launcher image a VMI is currently running with. + OutdatedLauncherImageLabel string = "kubevirt.io/outdatedLauncherImage" + // Namespace recommended by Kubernetes for commonly recognized labels + AppLabelPrefix = "app.kubernetes.io" + // This label is commonly used by 3rd party management tools to identify + // an application's name. + AppNameLabel = AppLabelPrefix + "/name" + // This label is commonly used by 3rd party management tools to identify + // an application's version. + AppVersionLabel = AppLabelPrefix + "/version" + // This label is commonly used by 3rd party management tools to identify + // a higher level application. + AppPartOfLabel = AppLabelPrefix + "/part-of" + // This label is commonly used by 3rd party management tools to identify + // the component this application is a part of. + AppComponentLabel = AppLabelPrefix + "/component" + // This label identifies each resource as part of KubeVirt + AppComponent = "kubevirt" + // This label will be set on all resources created by the operator + ManagedByLabel = AppLabelPrefix + "/managed-by" + ManagedByLabelOperatorValue = "virt-operator" + ManagedByLabelOperatorOldValue = "kubevirt-operator" + // This annotation represents the kubevirt version for an install strategy configmap. + InstallStrategyVersionAnnotation = "kubevirt.io/install-strategy-version" + // This annotation represents the kubevirt registry used for an install strategy configmap. + InstallStrategyRegistryAnnotation = "kubevirt.io/install-strategy-registry" + // This annotation represents the kubevirt deployment identifier used for an install strategy configmap. + InstallStrategyIdentifierAnnotation = "kubevirt.io/install-strategy-identifier" + // This annotation shows the enconding used for the manifests in the Install Strategy ConfigMap. + InstallStrategyConfigMapEncoding = "kubevirt.io/install-strategy-cm-encoding" + // This annotation is a hash of all customizations that live under spec.CustomizeComponents + KubeVirtCustomizeComponentAnnotationHash = "kubevirt.io/customizer-identifier" + // This annotation represents the kubevirt generation that was used to create a resource + KubeVirtGenerationAnnotation = "kubevirt.io/generation" + // This annotation represents that this object is for temporary use during updates + EphemeralBackupObject = "kubevirt.io/ephemeral-backup-object" + // This annotation represents that the annotated object is for temporary use during pod/volume provisioning + EphemeralProvisioningObject string = "kubevirt.io/ephemeral-provisioning" + + // This label indicates the object is a part of the install strategy retrieval process. + InstallStrategyLabel = "kubevirt.io/install-strategy" + + // Set by virt-operator to coordinate component deletion + VirtOperatorComponentFinalizer string = "kubevirt.io/virtOperatorFinalizer" + + // Set by VMI controller to ensure VMIs are processed during deletion + VirtualMachineInstanceFinalizer string = "foregroundDeleteVirtualMachine" + // Set By VM controller on VMIs to ensure VMIs are processed by VM controller during deletion + VirtualMachineControllerFinalizer string = "kubevirt.io/virtualMachineControllerFinalize" + VirtualMachineInstanceMigrationFinalizer string = "kubevirt.io/migrationJobFinalize" + CPUManager string = "cpumanager" + // This annotation is used to inject ignition data + // Used on VirtualMachineInstance. + IgnitionAnnotation string = "kubevirt.io/ignitiondata" + PlacePCIDevicesOnRootComplex string = "kubevirt.io/placePCIDevicesOnRootComplex" + + // This label represents supported cpu features on the node + CPUFeatureLabel = "cpu-feature.node.kubevirt.io/" + // This label represents supported cpu models on the node + CPUModelLabel = "cpu-model.node.kubevirt.io/" + SupportedHostModelMigrationCPU = "cpu-model-migration.node.kubevirt.io/" + CPUTimerLabel = "cpu-timer.node.kubevirt.io/" + // This label represents supported HyperV features on the node + HypervLabel = "hyperv.node.kubevirt.io/" + // This label represents vendor of cpu model on the node + CPUModelVendorLabel = "cpu-vendor.node.kubevirt.io/" + + // This label represents the host model CPU name + HostModelCPULabel = "host-model-cpu.node.kubevirt.io/" + // This label represents the host model required features + HostModelRequiredFeaturesLabel = "host-model-required-features.node.kubevirt.io/" + + LabellerSkipNodeAnnotation = "node-labeller.kubevirt.io/skip-node" + VirtualMachineLabel = AppLabel + "/vm" + MemfdMemoryBackend string = "kubevirt.io/memfd" + + MigrationSelectorLabel = "kubevirt.io/vmi-name" + + // This annotation represents vmi running nonroot implementation + DeprecatedNonRootVMIAnnotation = "kubevirt.io/nonroot" + + // This annotation is to keep virt launcher container alive when an VMI encounters a failure for debugging purpose + KeepLauncherAfterFailureAnnotation string = "kubevirt.io/keep-launcher-alive-after-failure" + + // MigrationTransportUnixAnnotation means that the VMI will be migrated using the unix URI + MigrationTransportUnixAnnotation string = "kubevirt.io/migrationTransportUnix" + + // MigrationUnschedulablePodTimeoutSecondsAnnotation represents a custom timeout period used for unschedulable target pods + // This exists for functional testing + MigrationUnschedulablePodTimeoutSecondsAnnotation string = "kubevirt.io/migrationUnschedulablePodTimeoutSeconds" + + // MigrationPendingPodTimeoutSecondsAnnotation represents a custom timeout period used for target pods stuck in pending for any reason + // This exists for functional testing + MigrationPendingPodTimeoutSecondsAnnotation string = "kubevirt.io/migrationPendingPodTimeoutSeconds" + + // CustomLibvirtLogFiltersAnnotation can be used to customized libvirt log filters. Example value could be + // "3:remote 4:event 3:util.json 3:util.object 3:util.dbus 3:util.netlink 3:node_device 3:rpc 3:access 1:*". + // For more info: https://libvirt.org/kbase/debuglogs.html + CustomLibvirtLogFiltersAnnotation string = "kubevirt.io/libvirt-log-filters" + + // RealtimeLabel marks the node as capable of running realtime workloads + RealtimeLabel string = "kubevirt.io/realtime" + + // VirtualMachineUnpaused is a custom pod condition set for the virt-launcher pod. + // It's used as a readiness gate to prevent paused VMs from being marked as ready. + VirtualMachineUnpaused k8sv1.PodConditionType = "kubevirt.io/virtual-machine-unpaused" + + // SEVLabel marks the node as capable of running workloads with SEV + SEVLabel string = "kubevirt.io/sev" + + // FlavorAnnotation is the name of a VirtualMachineFlavor + FlavorAnnotation string = "kubevirt.io/flavor-name" + + // ClusterFlavorAnnotation is the name of a VirtualMachineClusterFlavor + ClusterFlavorAnnotation string = "kubevirt.io/cluster-flavor-name" + + // FlavorAnnotation is the name of a VirtualMachinePreference + PreferenceAnnotation string = "kubevirt.io/preference-name" + + // ClusterFlavorAnnotation is the name of a VirtualMachinePreferenceFlavor + ClusterPreferenceAnnotation string = "kubevirt.io/cluster-preference-name" + + // VirtualMachinePoolRevisionName is used to store the vmpool revision's name this object + // originated from. + VirtualMachinePoolRevisionName string = "kubevirt.io/vm-pool-revision-name" + + // VirtualMachineNameLabel is the name of the Virtual Machine + VirtualMachineNameLabel string = "vm.kubevirt.io/name" +) + +func NewVMI(name string, uid types.UID) *VirtualMachineInstance { + return &VirtualMachineInstance{ + Spec: VirtualMachineInstanceSpec{}, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + UID: uid, + Namespace: k8sv1.NamespaceDefault, + }, + Status: VirtualMachineInstanceStatus{}, + TypeMeta: metav1.TypeMeta{ + APIVersion: GroupVersion.String(), + Kind: VirtualMachineInstanceGroupVersionKind.Kind, + }, + } +} + +type SyncEvent string + +const ( + Created SyncEvent = "Created" + Deleted SyncEvent = "Deleted" + PresetFailed SyncEvent = "PresetFailed" + Override SyncEvent = "Override" + Started SyncEvent = "Started" + ShuttingDown SyncEvent = "ShuttingDown" + Stopped SyncEvent = "Stopped" + PreparingTarget SyncEvent = "PreparingTarget" + Migrating SyncEvent = "Migrating" + Migrated SyncEvent = "Migrated" + SyncFailed SyncEvent = "SyncFailed" + Resumed SyncEvent = "Resumed" + AccessCredentialsSyncFailed SyncEvent = "AccessCredentialsSyncFailed" + AccessCredentialsSyncSuccess SyncEvent = "AccessCredentialsSyncSuccess" +) + +func (s SyncEvent) String() string { + return string(s) +} + +// TODO Namespace could be different, also store it somewhere in the domain, so that we can report deletes on handler startup properly +func NewVMIReferenceFromName(name string) *VirtualMachineInstance { + return NewVMIReferenceFromNameWithNS(k8sv1.NamespaceDefault, name) +} + +func NewVMIReferenceFromNameWithNS(namespace string, name string) *VirtualMachineInstance { + vmi := &VirtualMachineInstance{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + SelfLink: fmt.Sprintf("/apis/%s/namespaces/%s/virtualmachineinstances/%s", GroupVersion.String(), namespace, name), + }, + } + vmi.SetGroupVersionKind(schema.GroupVersionKind{Group: GroupVersion.Group, Kind: "VirtualMachineInstance", Version: GroupVersion.Version}) + return vmi +} + +func NewVMIReferenceWithUUID(namespace string, name string, uuid types.UID) *VirtualMachineInstance { + vmi := NewVMIReferenceFromNameWithNS(namespace, name) + vmi.UID = uuid + return vmi +} + +type VMISelector struct { + // Name of the VirtualMachineInstance to migrate + Name string `json:"name" valid:"required"` +} + +func NewVMReferenceFromNameWithNS(namespace string, name string) *VirtualMachine { + vm := &VirtualMachine{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + SelfLink: fmt.Sprintf("/apis/%s/namespaces/%s/virtualmachines/%s", GroupVersion.String(), namespace, name), + }, + } + vm.SetGroupVersionKind(schema.GroupVersionKind{Group: GroupVersion.Group, Kind: "VirtualMachine", Version: GroupVersion.Version}) + return vm +} + +// Given a VirtualMachineInstance, update all NodeSelectorTerms with anti-affinity for that VirtualMachineInstance's node. +// This is useful for the case when a migration away from a node must occur. +// This method returns the full Affinity structure updated the anti affinity terms +func UpdateAntiAffinityFromVMINode(pod *k8sv1.Pod, vmi *VirtualMachineInstance) *k8sv1.Affinity { + if pod.Spec.Affinity == nil { + pod.Spec.Affinity = &k8sv1.Affinity{} + } + + if pod.Spec.Affinity.NodeAffinity == nil { + pod.Spec.Affinity.NodeAffinity = &k8sv1.NodeAffinity{} + } + + if pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { + pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = &k8sv1.NodeSelector{} + } + + selector := pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution + terms := selector.NodeSelectorTerms + + if len(terms) == 0 { + selector.NodeSelectorTerms = append(terms, k8sv1.NodeSelectorTerm{}) + terms = selector.NodeSelectorTerms + } + + for idx, term := range terms { + if term.MatchExpressions == nil { + term.MatchExpressions = []k8sv1.NodeSelectorRequirement{} + } + + term.MatchExpressions = append(term.MatchExpressions, PrepareVMINodeAntiAffinitySelectorRequirement(vmi)) + selector.NodeSelectorTerms[idx] = term + } + + return pod.Spec.Affinity +} + +// Given a VirtualMachineInstance, create a NodeSelectorTerm with anti-affinity for that VirtualMachineInstance's node. +// This is useful for the case when a migration away from a node must occur. +func PrepareVMINodeAntiAffinitySelectorRequirement(vmi *VirtualMachineInstance) k8sv1.NodeSelectorRequirement { + return k8sv1.NodeSelectorRequirement{ + Key: "kubernetes.io/hostname", + Operator: k8sv1.NodeSelectorOpNotIn, + Values: []string{vmi.Status.NodeName}, + } +} + +// VirtualMachineInstance is *the* VirtualMachineInstance Definition. It represents a virtual machine in the runtime environment of kubernetes. +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type VirtualMachineInstanceReplicaSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + // VirtualMachineInstance Spec contains the VirtualMachineInstance specification. + Spec VirtualMachineInstanceReplicaSetSpec `json:"spec" valid:"required"` + // Status is the high level overview of how the VirtualMachineInstance is doing. It contains information available to controllers and users. + // +nullable + Status VirtualMachineInstanceReplicaSetStatus `json:"status,omitempty"` +} + +// VMIList is a list of VMIs +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstanceReplicaSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachineInstanceReplicaSet `json:"items"` +} + +type VirtualMachineInstanceReplicaSetSpec struct { + // Number of desired pods. This is a pointer to distinguish between explicit + // zero and not specified. Defaults to 1. + // +optional + Replicas *int32 `json:"replicas,omitempty"` + + // Label selector for pods. Existing ReplicaSets whose pods are + // selected by this will be the ones affected by this deployment. + Selector *metav1.LabelSelector `json:"selector" valid:"required"` + + // Template describes the pods that will be created. + Template *VirtualMachineInstanceTemplateSpec `json:"template" valid:"required"` + + // Indicates that the replica set is paused. + // +optional + Paused bool `json:"paused,omitempty" protobuf:"varint,7,opt,name=paused"` +} + +type VirtualMachineInstanceReplicaSetStatus struct { + // Total number of non-terminated pods targeted by this deployment (their labels match the selector). + // +optional + Replicas int32 `json:"replicas,omitempty" protobuf:"varint,2,opt,name=replicas"` + + // The number of ready replicas for this replica set. + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,4,opt,name=readyReplicas"` + + Conditions []VirtualMachineInstanceReplicaSetCondition `json:"conditions,omitempty" optional:"true"` + + // Canonical form of the label selector for HPA which consumes it through the scale subresource. + LabelSelector string `json:"labelSelector,omitempty"` +} + +type VirtualMachineInstanceReplicaSetCondition struct { + Type VirtualMachineInstanceReplicaSetConditionType `json:"type"` + Status k8sv1.ConditionStatus `json:"status"` + // +nullable + LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"` + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +type VirtualMachineInstanceReplicaSetConditionType string + +const ( + // VirtualMachineInstanceReplicaSetReplicaFailure is added in a replica set when one of its vmis + // fails to be created due to insufficient quota, limit ranges, pod security policy, node selectors, + // etc. or deleted due to kubelet being down or finalizers are failing. + VirtualMachineInstanceReplicaSetReplicaFailure VirtualMachineInstanceReplicaSetConditionType = "ReplicaFailure" + + // VirtualMachineInstanceReplicaSetReplicaPaused is added in a replica set when the replica set got paused by the controller. + // After this condition was added, it is safe to remove or add vmis by hand and adjust the replica count by hand. + VirtualMachineInstanceReplicaSetReplicaPaused VirtualMachineInstanceReplicaSetConditionType = "ReplicaPaused" +) + +type DataVolumeTemplateDummyStatus struct{} + +type DataVolumeTemplateSpec struct { + // TypeMeta only exists on DataVolumeTemplate for API backwards compatibility + // this field is not used by our controllers and is a no-op. + // +nullable + metav1.TypeMeta `json:",inline"` + // +kubebuilder:pruning:PreserveUnknownFields + // +nullable + metav1.ObjectMeta `json:"metadata,omitempty"` + // DataVolumeSpec contains the DataVolume specification. + Spec cdiv1.DataVolumeSpec `json:"spec"` + + // DataVolumeTemplateDummyStatus is here simply for backwards compatibility with + // a previous API. + // +nullable + // +optional + Status *DataVolumeTemplateDummyStatus `json:"status,omitempty"` +} + +type VirtualMachineInstanceTemplateSpec struct { + // +kubebuilder:pruning:PreserveUnknownFields + // +nullable + ObjectMeta metav1.ObjectMeta `json:"metadata,omitempty"` + // VirtualMachineInstance Spec contains the VirtualMachineInstance specification. + Spec VirtualMachineInstanceSpec `json:"spec,omitempty" valid:"required"` +} + +// VirtualMachineInstanceMigration represents the object tracking a VMI's migration +// to another host in the cluster +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type VirtualMachineInstanceMigration struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec VirtualMachineInstanceMigrationSpec `json:"spec" valid:"required"` + Status VirtualMachineInstanceMigrationStatus `json:"status,omitempty"` +} + +// VirtualMachineInstanceMigrationList is a list of VirtualMachineMigrations +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstanceMigrationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachineInstanceMigration `json:"items"` +} + +type VirtualMachineInstanceMigrationSpec struct { + // The name of the VMI to perform the migration on. VMI must exist in the migration objects namespace + VMIName string `json:"vmiName,omitempty" valid:"required"` +} + +// VirtualMachineInstanceMigration reprents information pertaining to a VMI's migration. +type VirtualMachineInstanceMigrationStatus struct { + Phase VirtualMachineInstanceMigrationPhase `json:"phase,omitempty"` + Conditions []VirtualMachineInstanceMigrationCondition `json:"conditions,omitempty"` +} + +// VirtualMachineInstanceMigrationPhase is a label for the condition of a VirtualMachineInstanceMigration at the current time. +type VirtualMachineInstanceMigrationPhase string + +// These are the valid migration phases +const ( + MigrationPhaseUnset VirtualMachineInstanceMigrationPhase = "" + // The migration is accepted by the system + MigrationPending VirtualMachineInstanceMigrationPhase = "Pending" + // The migration's target pod is being scheduled + MigrationScheduling VirtualMachineInstanceMigrationPhase = "Scheduling" + // The migration's target pod is running + MigrationScheduled VirtualMachineInstanceMigrationPhase = "Scheduled" + // The migration's target pod is being prepared for migration + MigrationPreparingTarget VirtualMachineInstanceMigrationPhase = "PreparingTarget" + // The migration's target pod is prepared and ready for migration + MigrationTargetReady VirtualMachineInstanceMigrationPhase = "TargetReady" + // The migration is in progress + MigrationRunning VirtualMachineInstanceMigrationPhase = "Running" + // The migration passed + MigrationSucceeded VirtualMachineInstanceMigrationPhase = "Succeeded" + // The migration failed + MigrationFailed VirtualMachineInstanceMigrationPhase = "Failed" +) + +// VirtualMachineInstancePreset defines a VMI spec.domain to be applied to all VMIs that match the provided label selector +// More info: https://kubevirt.io/user-guide/virtual_machines/presets/#overrides +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type VirtualMachineInstancePreset struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + // VirtualMachineInstance Spec contains the VirtualMachineInstance specification. + Spec VirtualMachineInstancePresetSpec `json:"spec,omitempty" valid:"required"` +} + +// VirtualMachineInstancePresetList is a list of VirtualMachinePresets +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstancePresetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachineInstancePreset `json:"items"` +} + +type VirtualMachineInstancePresetSpec struct { + // Selector is a label query over a set of VMIs. + // Required. + Selector metav1.LabelSelector `json:"selector"` + // Domain is the same object type as contained in VirtualMachineInstanceSpec + Domain *DomainSpec `json:"domain,omitempty"` +} + +func NewVirtualMachinePreset(name string, selector metav1.LabelSelector) *VirtualMachineInstancePreset { + return &VirtualMachineInstancePreset{ + Spec: VirtualMachineInstancePresetSpec{ + Selector: selector, + Domain: &DomainSpec{}, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: k8sv1.NamespaceDefault, + }, + TypeMeta: metav1.TypeMeta{ + APIVersion: GroupVersion.String(), + Kind: VirtualMachineInstancePresetGroupVersionKind.Kind, + }, + } +} + +// VirtualMachine handles the VirtualMachines that are not running +// or are in a stopped state +// The VirtualMachine contains the template to create the +// VirtualMachineInstance. It also mirrors the running state of the created +// VirtualMachineInstance in its status. +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type VirtualMachine struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + // Spec contains the specification of VirtualMachineInstance created + Spec VirtualMachineSpec `json:"spec" valid:"required"` + // Status holds the current state of the controller and brief information + // about its associated VirtualMachineInstance + Status VirtualMachineStatus `json:"status,omitempty"` +} + +// Return the current runStrategy for the VirtualMachine +// if vm.spec.running is set, that will be mapped to runStrategy: +// false: RunStrategyHalted +// true: RunStrategyAlways +func (vm *VirtualMachine) RunStrategy() (VirtualMachineRunStrategy, error) { + if vm.Spec.Running != nil && vm.Spec.RunStrategy != nil { + return RunStrategyUnknown, fmt.Errorf("running and runstrategy are mutually exclusive") + } + RunStrategy := RunStrategyHalted + if vm.Spec.Running != nil { + if (*vm.Spec.Running) == true { + RunStrategy = RunStrategyAlways + } + } else if vm.Spec.RunStrategy != nil { + RunStrategy = *vm.Spec.RunStrategy + } + return RunStrategy, nil +} + +// VirtualMachineList is a list of virtualmachines +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachine `json:"items"` +} + +// VirtualMachineRunStrategy is a label for the requested VirtualMachineInstance Running State at the current time. +type VirtualMachineRunStrategy string + +// These are the valid VMI run strategies +const ( + // Placeholder. Not a valid RunStrategy. + RunStrategyUnknown VirtualMachineRunStrategy = "" + // VMI should always be running. + RunStrategyAlways VirtualMachineRunStrategy = "Always" + // VMI should never be running. + RunStrategyHalted VirtualMachineRunStrategy = "Halted" + // VMI can be started/stopped using API endpoints. + RunStrategyManual VirtualMachineRunStrategy = "Manual" + // VMI will initially be running--and restarted if a failure occurs. + // It will not be restarted upon successful completion. + RunStrategyRerunOnFailure VirtualMachineRunStrategy = "RerunOnFailure" + // VMI will run once and not be restarted upon completion regardless + // if the completion is of phase Failure or Success + RunStrategyOnce VirtualMachineRunStrategy = "Once" +) + +// VirtualMachineSpec describes how the proper VirtualMachine +// should look like +type VirtualMachineSpec struct { + // Running controls whether the associatied VirtualMachineInstance is created or not + // Mutually exclusive with RunStrategy + Running *bool `json:"running,omitempty" optional:"true"` + + // Running state indicates the requested running state of the VirtualMachineInstance + // mutually exclusive with Running + RunStrategy *VirtualMachineRunStrategy `json:"runStrategy,omitempty" optional:"true"` + + // FlavorMatcher references a flavor that is used to fill fields in Template + Flavor *FlavorMatcher `json:"flavor,omitempty" optional:"true"` + + // PreferenceMatcher references a set of preference that is used to fill fields in Template + Preference *PreferenceMatcher `json:"preference,omitempty" optional:"true"` + + // Template is the direct specification of VirtualMachineInstance + Template *VirtualMachineInstanceTemplateSpec `json:"template"` + + // dataVolumeTemplates is a list of dataVolumes that the VirtualMachineInstance template can reference. + // DataVolumes in this list are dynamically created for the VirtualMachine and are tied to the VirtualMachine's life-cycle. + DataVolumeTemplates []DataVolumeTemplateSpec `json:"dataVolumeTemplates,omitempty"` +} + +// StateChangeRequestType represents the existing state change requests that are possible +type StateChangeRequestAction string + +// These are the currently defined state change requests +const ( + StartRequest StateChangeRequestAction = "Start" + StopRequest StateChangeRequestAction = "Stop" +) + +// VirtualMachinePrintableStatus is a human readable, high-level representation of the status of the virtual machine. +type VirtualMachinePrintableStatus string + +// A list of statuses defined for virtual machines +const ( + // VirtualMachineStatusStopped indicates that the virtual machine is currently stopped and isn't expected to start. + VirtualMachineStatusStopped VirtualMachinePrintableStatus = "Stopped" + // VirtualMachineStatusProvisioning indicates that cluster resources associated with the virtual machine + // (e.g., DataVolumes) are being provisioned and prepared. + VirtualMachineStatusProvisioning VirtualMachinePrintableStatus = "Provisioning" + // VirtualMachineStatusStarting indicates that the virtual machine is being prepared for running. + VirtualMachineStatusStarting VirtualMachinePrintableStatus = "Starting" + // VirtualMachineStatusRunning indicates that the virtual machine is running. + VirtualMachineStatusRunning VirtualMachinePrintableStatus = "Running" + // VirtualMachineStatusPaused indicates that the virtual machine is paused. + VirtualMachineStatusPaused VirtualMachinePrintableStatus = "Paused" + // VirtualMachineStatusStopping indicates that the virtual machine is in the process of being stopped. + VirtualMachineStatusStopping VirtualMachinePrintableStatus = "Stopping" + // VirtualMachineStatusTerminating indicates that the virtual machine is in the process of deletion, + // as well as its associated resources (VirtualMachineInstance, DataVolumes, …). + VirtualMachineStatusTerminating VirtualMachinePrintableStatus = "Terminating" + // VirtualMachineStatusCrashLoopBackOff indicates that the virtual machine is currently in a crash loop waiting to be retried. + VirtualMachineStatusCrashLoopBackOff VirtualMachinePrintableStatus = "CrashLoopBackOff" + // VirtualMachineStatusMigrating indicates that the virtual machine is in the process of being migrated + // to another host. + VirtualMachineStatusMigrating VirtualMachinePrintableStatus = "Migrating" + // VirtualMachineStatusUnknown indicates that the state of the virtual machine could not be obtained, + // typically due to an error in communicating with the host on which it's running. + VirtualMachineStatusUnknown VirtualMachinePrintableStatus = "Unknown" + // VirtualMachineStatusUnschedulable indicates that an error has occurred while scheduling the virtual machine, + // e.g. due to unsatisfiable resource requests or unsatisfiable scheduling constraints. + VirtualMachineStatusUnschedulable VirtualMachinePrintableStatus = "ErrorUnschedulable" + // VirtualMachineStatusErrImagePull indicates that an error has occured while pulling an image for + // a containerDisk VM volume. + VirtualMachineStatusErrImagePull VirtualMachinePrintableStatus = "ErrImagePull" + // VirtualMachineStatusImagePullBackOff indicates that an error has occured while pulling an image for + // a containerDisk VM volume, and that kubelet is backing off before retrying. + VirtualMachineStatusImagePullBackOff VirtualMachinePrintableStatus = "ImagePullBackOff" + // VirtualMachineStatusPvcNotFound indicates that the virtual machine references a PVC volume which doesn't exist. + VirtualMachineStatusPvcNotFound VirtualMachinePrintableStatus = "ErrorPvcNotFound" + // VirtualMachineStatusDataVolumeNotFound indicates that the virtual machine references a DataVolume volume which doesn't exist. + VirtualMachineStatusDataVolumeNotFound VirtualMachinePrintableStatus = "ErrorDataVolumeNotFound" + // VirtualMachineStatusDataVolumeError indicates that an error has been reported by one of the DataVolumes + // referenced by the virtual machines. + VirtualMachineStatusDataVolumeError VirtualMachinePrintableStatus = "DataVolumeError" + // VirtualMachineStatusWaitingForVolumeBinding indicates that some PersistentVolumeClaims backing + // the virtual machine volume are still not bound. + VirtualMachineStatusWaitingForVolumeBinding VirtualMachinePrintableStatus = "WaitingForVolumeBinding" +) + +// VirtualMachineStartFailure tracks VMIs which failed to transition successfully +// to running using the VM status +type VirtualMachineStartFailure struct { + ConsecutiveFailCount int `json:"consecutiveFailCount,omitempty"` + LastFailedVMIUID types.UID `json:"lastFailedVMIUID,omitempty"` + RetryAfterTimestamp *metav1.Time `json:"retryAfterTimestamp,omitempty"` +} + +// VirtualMachineStatus represents the status returned by the +// controller to describe how the VirtualMachine is doing +type VirtualMachineStatus struct { + // SnapshotInProgress is the name of the VirtualMachineSnapshot currently executing + SnapshotInProgress *string `json:"snapshotInProgress,omitempty"` + // RestoreInProgress is the name of the VirtualMachineRestore currently executing + RestoreInProgress *string `json:"restoreInProgress,omitempty"` + // Created indicates if the virtual machine is created in the cluster + Created bool `json:"created,omitempty"` + // Ready indicates if the virtual machine is running and ready + Ready bool `json:"ready,omitempty"` + // PrintableStatus is a human readable, high-level representation of the status of the virtual machine + PrintableStatus VirtualMachinePrintableStatus `json:"printableStatus,omitempty"` + // Hold the state information of the VirtualMachine and its VirtualMachineInstance + Conditions []VirtualMachineCondition `json:"conditions,omitempty" optional:"true"` + // StateChangeRequests indicates a list of actions that should be taken on a VMI + // e.g. stop a specific VMI then start a new one. + StateChangeRequests []VirtualMachineStateChangeRequest `json:"stateChangeRequests,omitempty" optional:"true"` + // VolumeRequests indicates a list of volumes add or remove from the VMI template and + // hotplug on an active running VMI. + // +listType=atomic + VolumeRequests []VirtualMachineVolumeRequest `json:"volumeRequests,omitempty" optional:"true"` + + // VolumeSnapshotStatuses indicates a list of statuses whether snapshotting is + // supported by each volume. + VolumeSnapshotStatuses []VolumeSnapshotStatus `json:"volumeSnapshotStatuses,omitempty" optional:"true"` + + // StartFailure tracks consecutive VMI startup failures for the purposes of + // crash loop backoffs + // +nullable + // +optional + StartFailure *VirtualMachineStartFailure `json:"startFailure,omitempty" optional:"true"` + + // MemoryDumpRequest tracks memory dump request phase and info of getting a memory + // dump to the given pvc + // +nullable + // +optional + MemoryDumpRequest *VirtualMachineMemoryDumpRequest `json:"memoryDumpRequest,omitempty" optional:"true"` +} + +type VolumeSnapshotStatus struct { + // Volume name + Name string `json:"name"` + // True if the volume supports snapshotting + Enabled bool `json:"enabled"` + // Empty if snapshotting is enabled, contains reason otherwise + Reason string `json:"reason,omitempty" optional:"true"` +} + +type VirtualMachineVolumeRequest struct { + // AddVolumeOptions when set indicates a volume should be added. The details + // within this field specify how to add the volume + AddVolumeOptions *AddVolumeOptions `json:"addVolumeOptions,omitempty" optional:"true"` + // RemoveVolumeOptions when set indicates a volume should be removed. The details + // within this field specify how to add the volume + RemoveVolumeOptions *RemoveVolumeOptions `json:"removeVolumeOptions,omitempty" optional:"true"` +} + +type VirtualMachineStateChangeRequest struct { + // Indicates the type of action that is requested. e.g. Start or Stop + Action StateChangeRequestAction `json:"action"` + // Provides additional data in order to perform the Action + Data map[string]string `json:"data,omitempty" optional:"true"` + // Indicates the UUID of an existing Virtual Machine Instance that this change request applies to -- if applicable + UID *types.UID `json:"uid,omitempty" optional:"true" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/kubernetes/pkg/types.UID"` +} + +// VirtualMachineCondition represents the state of VirtualMachine +type VirtualMachineCondition struct { + Type VirtualMachineConditionType `json:"type"` + Status k8sv1.ConditionStatus `json:"status"` + // +nullable + LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"` + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +type VirtualMachineConditionType string + +const ( + // VirtualMachineFailure is added in a virtual machine when its vmi + // fails to be created due to insufficient quota, limit ranges, pod security policy, node selectors, + // etc. or deleted due to kubelet being down or finalizers are failing. + VirtualMachineFailure VirtualMachineConditionType = "Failure" + + // VirtualMachineReady is copied to the virtual machine from its vmi + VirtualMachineReady VirtualMachineConditionType = "Ready" + + // VirtualMachinePaused is added in a virtual machine when its vmi + // signals with its own condition that it is paused. + VirtualMachinePaused VirtualMachineConditionType = "Paused" +) + +type HostDiskType string + +const ( + // if disk does not exist at the given path, + // a disk image will be created there + HostDiskExistsOrCreate HostDiskType = "DiskOrCreate" + // a disk image must exist at given disk path + HostDiskExists HostDiskType = "Disk" +) + +type NetworkInterfaceType string + +const ( + // Virtual machine instance bride interface + BridgeInterface NetworkInterfaceType = "bridge" + // Virtual machine instance slirp interface + SlirpInterface NetworkInterfaceType = "slirp" + // Virtual machine instance masquerade interface + MasqueradeInterface NetworkInterfaceType = "masquerade" +) + +type DriverCache string + +type DriverIO string + +const ( + // CacheNone - I/O from the guest is not cached on the host, but may be kept in a writeback disk cache. + CacheNone DriverCache = "none" + // CacheWriteThrough - I/O from the guest is cached on the host but written through to the physical medium. + CacheWriteThrough DriverCache = "writethrough" + // CacheWriteBack - I/O from the guest is cached on the host. + CacheWriteBack DriverCache = "writeback" + + // IOThreads - User mode based threads with a shared lock that perform I/O tasks. Can impact performance but offers + // more predictable behaviour. This method is also takes fewer CPU cycles to submit I/O requests. + IOThreads DriverIO = "threads" + // IONative - Kernel native I/O tasks (AIO) offer a better performance but can block the VM if the file is not fully + // allocated so this method recommended only when the backing file/disk/etc is fully preallocated. + IONative DriverIO = "native" + // IODefault - Fallback to the default value from the kernel. With recent Kernel versions (for example RHEL-7) the + // default is AIO. + IODefault DriverIO = "default" +) + +// Handler defines a specific action that should be taken +// TODO: pass structured data to these actions, and document that data here. +type Handler struct { + // One and only one of the following should be specified. + // Exec specifies the action to take, it will be executed on the guest through the qemu-guest-agent. + // If the guest agent is not available, this probe will fail. + // +optional + Exec *k8sv1.ExecAction `json:"exec,omitempty" protobuf:"bytes,1,opt,name=exec"` + // GuestAgentPing contacts the qemu-guest-agent for availability checks. + // +optional + GuestAgentPing *GuestAgentPing `json:"guestAgentPing,omitempty"` + // HTTPGet specifies the http request to perform. + // +optional + HTTPGet *k8sv1.HTTPGetAction `json:"httpGet,omitempty"` + // TCPSocket specifies an action involving a TCP port. + // TCP hooks not yet supported + // TODO: implement a realistic TCP lifecycle hook + // +optional + TCPSocket *k8sv1.TCPSocketAction `json:"tcpSocket,omitempty"` +} + +// Probe describes a health check to be performed against a VirtualMachineInstance to determine whether it is +// alive or ready to receive traffic. +type Probe struct { + // The action taken to determine the health of a VirtualMachineInstance + Handler `json:",inline"` + // Number of seconds after the VirtualMachineInstance has started before liveness probes are initiated. + // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + // +optional + InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"` + // Number of seconds after which the probe times out. + // For exec probes the timeout fails the probe but does not terminate the command running on the guest. + // This means a blocking command can result in an increasing load on the guest. + // A small buffer will be added to the resulting workload exec probe to compensate for delays + // caused by the qemu guest exec mechanism. + // Defaults to 1 second. Minimum value is 1. + // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + // +optional + TimeoutSeconds int32 `json:"timeoutSeconds,omitempty"` + // How often (in seconds) to perform the probe. + // Default to 10 seconds. Minimum value is 1. + // +optional + PeriodSeconds int32 `json:"periodSeconds,omitempty"` + // Minimum consecutive successes for the probe to be considered successful after having failed. + // Defaults to 1. Must be 1 for liveness. Minimum value is 1. + // +optional + SuccessThreshold int32 `json:"successThreshold,omitempty"` + // Minimum consecutive failures for the probe to be considered failed after having succeeded. + // Defaults to 3. Minimum value is 1. + // +optional + FailureThreshold int32 `json:"failureThreshold,omitempty"` +} + +// KubeVirt represents the object deploying all KubeVirt resources +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +type KubeVirt struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec KubeVirtSpec `json:"spec" valid:"required"` + Status KubeVirtStatus `json:"status,omitempty"` +} + +// KubeVirtList is a list of KubeVirts +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type KubeVirtList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KubeVirt `json:"items"` +} + +type KubeVirtSelfSignConfiguration struct { + // Deprecated. Use CA.Duration instead + CARotateInterval *metav1.Duration `json:"caRotateInterval,omitempty"` + // Deprecated. Use Server.Duration instead + CertRotateInterval *metav1.Duration `json:"certRotateInterval,omitempty"` + // Deprecated. Use CA.Duration and CA.RenewBefore instead + CAOverlapInterval *metav1.Duration `json:"caOverlapInterval,omitempty"` + + // CA configuration + // CA certs are kept in the CA bundle as long as they are valid + CA *CertConfig `json:"ca,omitempty"` + + // Server configuration + // Certs are rotated and discarded + Server *CertConfig `json:"server,omitempty"` +} + +// CertConfig contains the tunables for TLS certificates +type CertConfig struct { + // The requested 'duration' (i.e. lifetime) of the Certificate. + Duration *metav1.Duration `json:"duration,omitempty"` + + // The amount of time before the currently issued certificate's "notAfter" + // time that we will begin to attempt to renew the certificate. + RenewBefore *metav1.Duration `json:"renewBefore,omitempty"` +} + +type KubeVirtCertificateRotateStrategy struct { + SelfSigned *KubeVirtSelfSignConfiguration `json:"selfSigned,omitempty"` +} + +type WorkloadUpdateMethod string + +const ( + // WorkloadUpdateMethodLiveMigrate allows VMIs which are capable of being + // migrated to automatically migrate during automated workload updates. + WorkloadUpdateMethodLiveMigrate WorkloadUpdateMethod = "LiveMigrate" + // WorkloadUpdateMethodEvict results in a VMI's pod being evicted. Unless the + // pod has a pod disruption budget allocated, the eviction will usually result in + // the VMI being shutdown. + // Depending on whether a VMI is backed by a VM or not, this will either result + // in a restart of the VM by rescheduling a new VMI, or the shutdown via eviction + // of a standalone VMI object. + WorkloadUpdateMethodEvict WorkloadUpdateMethod = "Evict" +) + +// +// KubeVirtWorkloadUpdateStrategy defines options related to updating a KubeVirt install +type KubeVirtWorkloadUpdateStrategy struct { + // WorkloadUpdateMethods defines the methods that can be used to disrupt workloads + // during automated workload updates. + // When multiple methods are present, the least disruptive method takes + // precedence over more disruptive methods. For example if both LiveMigrate and Shutdown + // methods are listed, only VMs which are not live migratable will be restarted/shutdown + // + // An empty list defaults to no automated workload updating + // + // +listType=atomic + // +optional + WorkloadUpdateMethods []WorkloadUpdateMethod `json:"workloadUpdateMethods,omitempty"` + + // BatchEvictionSize Represents the number of VMIs that can be forced updated per + // the BatchShutdownInteral interval + // + // Defaults to 10 + // + // +optional + BatchEvictionSize *int `json:"batchEvictionSize,omitempty"` + + // BatchEvictionInterval Represents the interval to wait before issuing the next + // batch of shutdowns + // + // Defaults to 1 minute + // + // +optional + BatchEvictionInterval *metav1.Duration `json:"batchEvictionInterval,omitempty"` +} + +type KubeVirtSpec struct { + // The image tag to use for the continer images installed. + // Defaults to the same tag as the operator's container image. + ImageTag string `json:"imageTag,omitempty"` + // The image registry to pull the container images from + // Defaults to the same registry the operator's container image is pulled from. + ImageRegistry string `json:"imageRegistry,omitempty"` + + // The ImagePullPolicy to use. + ImagePullPolicy k8sv1.PullPolicy `json:"imagePullPolicy,omitempty" valid:"required"` + + // The namespace Prometheus is deployed in + // Defaults to openshift-monitor + MonitorNamespace string `json:"monitorNamespace,omitempty"` + + // The namespace the service monitor will be deployed + // When ServiceMonitorNamespace is set, then we'll install the service monitor object in that namespace + // otherwise we will use the monitoring namespace. + ServiceMonitorNamespace string `json:"serviceMonitorNamespace,omitempty"` + + // The name of the Prometheus service account that needs read-access to KubeVirt endpoints + // Defaults to prometheus-k8s + MonitorAccount string `json:"monitorAccount,omitempty"` + + // WorkloadUpdateStrategy defines at the cluster level how to handle + // automated workload updates + WorkloadUpdateStrategy KubeVirtWorkloadUpdateStrategy `json:"workloadUpdateStrategy,omitempty"` + + // Specifies if kubevirt can be deleted if workloads are still present. + // This is mainly a precaution to avoid accidental data loss + UninstallStrategy KubeVirtUninstallStrategy `json:"uninstallStrategy,omitempty"` + + CertificateRotationStrategy KubeVirtCertificateRotateStrategy `json:"certificateRotateStrategy,omitempty"` + + // Designate the apps.kubevirt.io/version label for KubeVirt components. + // Useful if KubeVirt is included as part of a product. + // If ProductVersion is not specified, KubeVirt's version will be used. + ProductVersion string `json:"productVersion,omitempty"` + + // Designate the apps.kubevirt.io/part-of label for KubeVirt components. + // Useful if KubeVirt is included as part of a product. + // If ProductName is not specified, the part-of label will be omitted. + ProductName string `json:"productName,omitempty"` + + // Designate the apps.kubevirt.io/component label for KubeVirt components. + // Useful if KubeVirt is included as part of a product. + // If ProductComponent is not specified, the component label default value is kubevirt. + ProductComponent string `json:"productComponent,omitempty"` + + // holds kubevirt configurations. + // same as the virt-configMap + Configuration KubeVirtConfiguration `json:"configuration,omitempty"` + + // selectors and tolerations that should apply to KubeVirt infrastructure components + // +optional + Infra *ComponentConfig `json:"infra,omitempty"` + + // selectors and tolerations that should apply to KubeVirt workloads + // +optional + Workloads *ComponentConfig `json:"workloads,omitempty"` + + CustomizeComponents CustomizeComponents `json:"customizeComponents,omitempty"` +} + +type CustomizeComponents struct { + // +listType=atomic + Patches []CustomizeComponentsPatch `json:"patches,omitempty"` + + // Configure the value used for deployment and daemonset resources + Flags *Flags `json:"flags,omitempty"` +} + +// Flags will create a patch that will replace all flags for the container's +// command field. The only flags that will be used are those define. There are no +// guarantees around forward/backward compatibility. If set incorrectly this will +// cause the resource when rolled out to error until flags are updated. +type Flags struct { + API map[string]string `json:"api,omitempty"` + Controller map[string]string `json:"controller,omitempty"` + Handler map[string]string `json:"handler,omitempty"` +} + +type CustomizeComponentsPatch struct { + // +kubebuilder:validation:MinLength=1 + ResourceName string `json:"resourceName"` + // +kubebuilder:validation:MinLength=1 + ResourceType string `json:"resourceType"` + Patch string `json:"patch"` + Type PatchType `json:"type"` +} + +type PatchType string + +const ( + JSONPatchType PatchType = "json" + MergePatchType PatchType = "merge" + StrategicMergePatchType PatchType = "strategic" +) + +type KubeVirtUninstallStrategy string + +const ( + KubeVirtUninstallStrategyRemoveWorkloads KubeVirtUninstallStrategy = "RemoveWorkloads" + KubeVirtUninstallStrategyBlockUninstallIfWorkloadsExist KubeVirtUninstallStrategy = "BlockUninstallIfWorkloadsExist" +) + +// GenerationStatus keeps track of the generation for a given resource so that decisions about forced updates can be made. +type GenerationStatus struct { + // group is the group of the thing you're tracking + Group string `json:"group"` + // resource is the resource type of the thing you're tracking + Resource string `json:"resource"` + // namespace is where the thing you're tracking is + // +optional + Namespace string `json:"namespace,omitempty" optional:"true"` + // name is the name of the thing you're tracking + Name string `json:"name"` + // lastGeneration is the last generation of the workload controller involved + LastGeneration int64 `json:"lastGeneration"` + // hash is an optional field set for resources without generation that are content sensitive like secrets and configmaps + // +optional + Hash string `json:"hash,omitempty" optional:"true"` +} + +// KubeVirtStatus represents information pertaining to a KubeVirt deployment. +type KubeVirtStatus struct { + Phase KubeVirtPhase `json:"phase,omitempty"` + Conditions []KubeVirtCondition `json:"conditions,omitempty" optional:"true"` + OperatorVersion string `json:"operatorVersion,omitempty" optional:"true"` + TargetKubeVirtRegistry string `json:"targetKubeVirtRegistry,omitempty" optional:"true"` + TargetKubeVirtVersion string `json:"targetKubeVirtVersion,omitempty" optional:"true"` + TargetDeploymentConfig string `json:"targetDeploymentConfig,omitempty" optional:"true"` + TargetDeploymentID string `json:"targetDeploymentID,omitempty" optional:"true"` + ObservedKubeVirtRegistry string `json:"observedKubeVirtRegistry,omitempty" optional:"true"` + ObservedKubeVirtVersion string `json:"observedKubeVirtVersion,omitempty" optional:"true"` + ObservedDeploymentConfig string `json:"observedDeploymentConfig,omitempty" optional:"true"` + ObservedDeploymentID string `json:"observedDeploymentID,omitempty" optional:"true"` + OutdatedVirtualMachineInstanceWorkloads *int `json:"outdatedVirtualMachineInstanceWorkloads,omitempty" optional:"true"` + ObservedGeneration *int64 `json:"observedGeneration,omitempty"` + // +listType=atomic + Generations []GenerationStatus `json:"generations,omitempty" optional:"true"` +} + +// KubeVirtPhase is a label for the phase of a KubeVirt deployment at the current time. +type KubeVirtPhase string + +// These are the valid KubeVirt deployment phases +const ( + // The deployment is processing + KubeVirtPhaseDeploying KubeVirtPhase = "Deploying" + // The deployment succeeded + KubeVirtPhaseDeployed KubeVirtPhase = "Deployed" + // The deletion is processing + KubeVirtPhaseDeleting KubeVirtPhase = "Deleting" + // The deletion succeeeded + KubeVirtPhaseDeleted KubeVirtPhase = "Deleted" +) + +// KubeVirtCondition represents a condition of a KubeVirt deployment +type KubeVirtCondition struct { + Type KubeVirtConditionType `json:"type"` + Status k8sv1.ConditionStatus `json:"status"` + // +optional + // +nullable + LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"` + // +optional + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +type KubeVirtConditionType string + +// These are the valid KubeVirt condition types +const ( + // Whether the deployment or deletion was successful (only used if false) + KubeVirtConditionSynchronized KubeVirtConditionType = "Synchronized" + // Whether all resources were created and up-to-date + KubeVirtConditionCreated KubeVirtConditionType = "Created" + + // Conditions for HCO, see https://github.com/kubevirt/hyperconverged-cluster-operator/blob/master/docs/conditions.md + // Whether KubeVirt is functional and available in the cluster. + KubeVirtConditionAvailable KubeVirtConditionType = "Available" + // Whether the operator is actively making changes to KubeVirt + KubeVirtConditionProgressing KubeVirtConditionType = "Progressing" + // Whether KubeVirt is not functioning completely + KubeVirtConditionDegraded KubeVirtConditionType = "Degraded" +) + +const ( + EvictionStrategyNone EvictionStrategy = "None" + EvictionStrategyLiveMigrate EvictionStrategy = "LiveMigrate" + EvictionStrategyExternal EvictionStrategy = "External" +) + +// RestartOptions may be provided when deleting an API object. +type RestartOptions struct { + metav1.TypeMeta `json:",inline"` + + // The duration in seconds before the object should be force-restarted. Value must be non-negative integer. + // The value zero indicates, restart immediately. If this value is nil, the default grace period for deletion of the corresponding VMI for the + // specified type will be used to determine on how much time to give the VMI to restart. + // Defaults to a per object value if not specified. zero means restart immediately. + // Allowed Values: nil and 0 + // +optional + GracePeriodSeconds *int64 `json:"gracePeriodSeconds,omitempty" protobuf:"varint,1,opt,name=gracePeriodSeconds"` + + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,2,rep,name=dryRun"` +} + +// StartOptions may be provided on start request. +type StartOptions struct { + metav1.TypeMeta `json:",inline"` + + // Indicates that VM will be started in paused state. + // +optional + Paused bool `json:"paused,omitempty" protobuf:"varint,7,opt,name=paused"` + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,5,rep,name=dryRun"` +} + +// PauseOptions may be provided on pause request. +type PauseOptions struct { + metav1.TypeMeta `json:",inline"` + + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"` +} + +// UnpauseOptions may be provided on unpause request. +type UnpauseOptions struct { + metav1.TypeMeta `json:",inline"` + + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"` +} + +const ( + StartRequestDataPausedKey string = "paused" + StartRequestDataPausedTrue string = "true" +) + +// StopOptions may be provided when deleting an API object. +type StopOptions struct { + metav1.TypeMeta `json:",inline"` + + // this updates the VMIs terminationGracePeriodSeconds during shutdown + // +optional + GracePeriod *int64 `json:"gracePeriod,omitempty" protobuf:"varint,1,opt,name=gracePeriod"` + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,2,rep,name=dryRun"` +} + +// MigrateOptions may be provided on migrate request. +type MigrateOptions struct { + metav1.TypeMeta `json:",inline"` + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"` +} + +// VirtualMachineInstanceGuestAgentInfo represents information from the installed guest agent +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstanceGuestAgentInfo struct { + metav1.TypeMeta `json:",inline"` + // GAVersion is a version of currently installed guest agent + GAVersion string `json:"guestAgentVersion,omitempty"` + // Return command list the guest agent supports + // +listType=atomic + SupportedCommands []GuestAgentCommandInfo `json:"supportedCommands,omitempty"` + // Hostname represents FQDN of a guest + Hostname string `json:"hostname,omitempty"` + // OS contains the guest operating system information + OS VirtualMachineInstanceGuestOSInfo `json:"os,omitempty"` + // Timezone is guest os current timezone + Timezone string `json:"timezone,omitempty"` + // UserList is a list of active guest OS users + UserList []VirtualMachineInstanceGuestOSUser `json:"userList,omitempty"` + // FSInfo is a guest os filesystem information containing the disk mapping and disk mounts with usage + FSInfo VirtualMachineInstanceFileSystemInfo `json:"fsInfo,omitempty"` + // FSFreezeStatus is the state of the fs of the guest + // it can be either frozen or thawed + FSFreezeStatus string `json:"fsFreezeStatus,omitempty"` +} + +// List of commands that QEMU guest agent supports +type GuestAgentCommandInfo struct { + Name string `json:"name"` + Enabled bool `json:"enabled,omitempty"` +} + +// VirtualMachineInstanceGuestOSUserList comprises the list of all active users on guest machine +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstanceGuestOSUserList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachineInstanceGuestOSUser `json:"items"` +} + +// VirtualMachineGuestOSUser is the single user of the guest os +type VirtualMachineInstanceGuestOSUser struct { + UserName string `json:"userName"` + Domain string `json:"domain,omitempty"` + LoginTime float64 `json:"loginTime,omitempty"` +} + +// VirtualMachineInstanceFileSystemInfo represents information regarding single guest os filesystem +type VirtualMachineInstanceFileSystemInfo struct { + Filesystems []VirtualMachineInstanceFileSystem `json:"disks"` +} + +// VirtualMachineInstanceFileSystemList comprises the list of all filesystems on guest machine +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualMachineInstanceFileSystemList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualMachineInstanceFileSystem `json:"items"` +} + +// VirtualMachineInstanceFileSystem represents guest os disk +type VirtualMachineInstanceFileSystem struct { + DiskName string `json:"diskName"` + MountPoint string `json:"mountPoint"` + FileSystemType string `json:"fileSystemType"` + UsedBytes int `json:"usedBytes"` + TotalBytes int `json:"totalBytes"` +} + +// FreezeUnfreezeTimeout represent the time unfreeze will be triggered if guest was not unfrozen by unfreeze command +type FreezeUnfreezeTimeout struct { + UnfreezeTimeout *metav1.Duration `json:"unfreezeTimeout"` +} + +// VirtualMachineMemoryDumpRequest represent the memory dump request phase and info +type VirtualMachineMemoryDumpRequest struct { + // ClaimName is the name of the pvc that will contain the memory dump + ClaimName string `json:"claimName"` + // Phase represents the memory dump phase + Phase MemoryDumpPhase `json:"phase"` + // StartTimestamp represents the time the memory dump started + StartTimestamp *metav1.Time `json:"startTimestamp,omitempty"` + // EndTimestamp represents the time the memory dump was completed + EndTimestamp *metav1.Time `json:"endTimestamp,omitempty"` + // FileName represents the name of the output file + FileName *string `json:"fileName,omitempty"` + // Message is a detailed message about failure of the memory dump + Message string `json:"message,omitempty"` +} + +type MemoryDumpPhase string + +const ( + // The memorydump is during pvc Associating + MemoryDumpAssociating MemoryDumpPhase = "Associating" + // The memorydump is in progress + MemoryDumpInProgress MemoryDumpPhase = "InProgress" + // The memorydump is being unmounted + MemoryDumpUnmounting MemoryDumpPhase = "Unmounting" + // The memorydump is completed + MemoryDumpCompleted MemoryDumpPhase = "Completed" + // The memorydump is being unbound + MemoryDumpDissociating MemoryDumpPhase = "Dissociating" + // The memorydump failed + MemoryDumpFailed MemoryDumpPhase = "Failed" +) + +// AddVolumeOptions is provided when dynamically hot plugging a volume and disk +type AddVolumeOptions struct { + // Name represents the name that will be used to map the + // disk to the corresponding volume. This overrides any name + // set inside the Disk struct itself. + Name string `json:"name"` + // Disk represents the hotplug disk that will be plugged into the running VMI + Disk *Disk `json:"disk"` + // VolumeSource represents the source of the volume to map to the disk. + VolumeSource *HotplugVolumeSource `json:"volumeSource"` + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty"` +} + +// RemoveVolumeOptions is provided when dynamically hot unplugging volume and disk +type RemoveVolumeOptions struct { + // Name represents the name that maps to both the disk and volume that + // should be removed + Name string `json:"name"` + // When present, indicates that modifications should not be + // persisted. An invalid or unrecognized dryRun directive will + // result in an error response and no further processing of the + // request. Valid values are: + // - All: all dry run stages will be processed + // +optional + // +listType=atomic + DryRun []string `json:"dryRun,omitempty"` +} + +type TokenBucketRateLimiter struct { + // QPS indicates the maximum QPS to the apiserver from this client. + // If it's zero, the component default will be used + QPS float32 `json:"qps"` + + // Maximum burst for throttle. + // If it's zero, the component default will be used + Burst int `json:"burst"` +} + +type RateLimiter struct { + TokenBucketRateLimiter *TokenBucketRateLimiter `json:"tokenBucketRateLimiter,omitempty"` +} + +// RESTClientConfiguration allows configuring certain aspects of the k8s rest client. +type RESTClientConfiguration struct { + //RateLimiter allows selecting and configuring different rate limiters for the k8s client. + RateLimiter *RateLimiter `json:"rateLimiter,omitempty"` +} + +// ReloadableComponentConfiguration holds all generic k8s configuration options which can +// be reloaded by components without requiring a restart. +type ReloadableComponentConfiguration struct { + //RestClient can be used to tune certain aspects of the k8s client in use. + RestClient *RESTClientConfiguration `json:"restClient,omitempty"` +} + +// KubeVirtConfiguration holds all kubevirt configurations +type KubeVirtConfiguration struct { + CPUModel string `json:"cpuModel,omitempty"` + CPURequest *resource.Quantity `json:"cpuRequest,omitempty"` + DeveloperConfiguration *DeveloperConfiguration `json:"developerConfiguration,omitempty"` + EmulatedMachines []string `json:"emulatedMachines,omitempty"` + ImagePullPolicy k8sv1.PullPolicy `json:"imagePullPolicy,omitempty"` + MigrationConfiguration *MigrationConfiguration `json:"migrations,omitempty"` + MachineType string `json:"machineType,omitempty"` + NetworkConfiguration *NetworkConfiguration `json:"network,omitempty"` + OVMFPath string `json:"ovmfPath,omitempty"` + SELinuxLauncherType string `json:"selinuxLauncherType,omitempty"` + DefaultRuntimeClass string `json:"defaultRuntimeClass,omitempty"` + SMBIOSConfig *SMBiosConfiguration `json:"smbios,omitempty"` + + // EvictionStrategy defines at the cluster level if the VirtualMachineInstance should be + // migrated instead of shut-off in case of a node drain. If the VirtualMachineInstance specific + // field is set it overrides the cluster level one. + EvictionStrategy *EvictionStrategy `json:"evictionStrategy,omitempty"` + + // deprecated + SupportedGuestAgentVersions []string `json:"supportedGuestAgentVersions,omitempty"` + MemBalloonStatsPeriod *uint32 `json:"memBalloonStatsPeriod,omitempty"` + PermittedHostDevices *PermittedHostDevices `json:"permittedHostDevices,omitempty"` + MediatedDevicesConfiguration *MediatedDevicesConfiguration `json:"mediatedDevicesConfiguration,omitempty"` + MinCPUModel string `json:"minCPUModel,omitempty"` + ObsoleteCPUModels map[string]bool `json:"obsoleteCPUModels,omitempty"` + VirtualMachineInstancesPerNode *int `json:"virtualMachineInstancesPerNode,omitempty"` + APIConfiguration *ReloadableComponentConfiguration `json:"apiConfiguration,omitempty"` + WebhookConfiguration *ReloadableComponentConfiguration `json:"webhookConfiguration,omitempty"` + ControllerConfiguration *ReloadableComponentConfiguration `json:"controllerConfiguration,omitempty"` + HandlerConfiguration *ReloadableComponentConfiguration `json:"handlerConfiguration,omitempty"` +} + +type SMBiosConfiguration struct { + Manufacturer string `json:"manufacturer,omitempty"` + Product string `json:"product,omitempty"` + Version string `json:"version,omitempty"` + Sku string `json:"sku,omitempty"` + Family string `json:"family,omitempty"` +} + +// MigrationConfiguration holds migration options +type MigrationConfiguration struct { + NodeDrainTaintKey *string `json:"nodeDrainTaintKey,omitempty"` + ParallelOutboundMigrationsPerNode *uint32 `json:"parallelOutboundMigrationsPerNode,omitempty"` + ParallelMigrationsPerCluster *uint32 `json:"parallelMigrationsPerCluster,omitempty"` + AllowAutoConverge *bool `json:"allowAutoConverge,omitempty"` + BandwidthPerMigration *resource.Quantity `json:"bandwidthPerMigration,omitempty"` + CompletionTimeoutPerGiB *int64 `json:"completionTimeoutPerGiB,omitempty"` + ProgressTimeout *int64 `json:"progressTimeout,omitempty"` + UnsafeMigrationOverride *bool `json:"unsafeMigrationOverride,omitempty"` + AllowPostCopy *bool `json:"allowPostCopy,omitempty"` + DisableTLS *bool `json:"disableTLS,omitempty"` + Network *string `json:"network,omitempty"` +} + +// DiskVerification holds container disks verification limits +type DiskVerification struct { + MemoryLimit *resource.Quantity `json:"memoryLimit"` +} + +// DeveloperConfiguration holds developer options +type DeveloperConfiguration struct { + FeatureGates []string `json:"featureGates,omitempty"` + LessPVCSpaceToleration int `json:"pvcTolerateLessSpaceUpToPercent,omitempty"` + MinimumReservePVCBytes uint64 `json:"minimumReservePVCBytes,omitempty"` + MemoryOvercommit int `json:"memoryOvercommit,omitempty"` + NodeSelectors map[string]string `json:"nodeSelectors,omitempty"` + // UseEmulation can be set to true to allow fallback to software emulation + // in case hardware-assisted emulation is not available. + UseEmulation bool `json:"useEmulation,omitempty"` + CPUAllocationRatio int `json:"cpuAllocationRatio,omitempty"` + // Allow overriding the automatically determined minimum TSC frequency of the cluster + // and fixate the minimum to this frequency. + MinimumClusterTSCFrequency *int64 `json:"minimumClusterTSCFrequency,omitempty"` + DiskVerification *DiskVerification `json:"diskVerification,omitempty"` + LogVerbosity *LogVerbosity `json:"logVerbosity,omitempty"` +} + +// LogVerbosity sets log verbosity level of various components +type LogVerbosity struct { + VirtAPI uint `json:"virtAPI,omitempty"` + VirtController uint `json:"virtController,omitempty"` + VirtHandler uint `json:"virtHandler,omitempty"` + VirtLauncher uint `json:"virtLauncher,omitempty"` + VirtOperator uint `json:"virtOperator,omitempty"` + // NodeVerbosity represents a map of nodes with a specific verbosity level + NodeVerbosity map[string]uint `json:"nodeVerbosity,omitempty"` +} + +// PermittedHostDevices holds information about devices allowed for passthrough +type PermittedHostDevices struct { + // +listType=atomic + PciHostDevices []PciHostDevice `json:"pciHostDevices,omitempty"` + // +listType=atomic + MediatedDevices []MediatedHostDevice `json:"mediatedDevices,omitempty"` +} + +// PciHostDevice represents a host PCI device allowed for passthrough +type PciHostDevice struct { + // The vendor_id:product_id tuple of the PCI device + PCIVendorSelector string `json:"pciVendorSelector"` + // The name of the resource that is representing the device. Exposed by + // a device plugin and requested by VMs. Typically of the form + // vendor.com/product_nameThe name of the resource that is representing + // the device. Exposed by a device plugin and requested by VMs. + // Typically of the form vendor.com/product_name + ResourceName string `json:"resourceName"` + // If true, KubeVirt will leave the allocation and monitoring to an + // external device plugin + ExternalResourceProvider bool `json:"externalResourceProvider,omitempty"` +} + +// MediatedHostDevice represents a host mediated device allowed for passthrough +type MediatedHostDevice struct { + MDEVNameSelector string `json:"mdevNameSelector"` + ResourceName string `json:"resourceName"` + ExternalResourceProvider bool `json:"externalResourceProvider,omitempty"` +} + +// MediatedDevicesConfiguration holds information about MDEV types to be defined, if available +type MediatedDevicesConfiguration struct { + // +listType=atomic + MediatedDevicesTypes []string `json:"mediatedDevicesTypes,omitempty"` + // +optional + // +listType=atomic + NodeMediatedDeviceTypes []NodeMediatedDeviceTypesConfig `json:"nodeMediatedDeviceTypes,omitempty"` +} + +// NodeMediatedDeviceTypesConfig holds information about MDEV types to be defined in a specifc node that matches the NodeSelector field. +// +k8s:openapi-gen=true +type NodeMediatedDeviceTypesConfig struct { + // NodeSelector is a selector which must be true for the vmi to fit on a node. + // Selector which must match a node's labels for the vmi to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + NodeSelector map[string]string `json:"nodeSelector"` + // +listType=atomic + MediatedDevicesTypes []string `json:"mediatedDevicesTypes"` +} + +// NetworkConfiguration holds network options +type NetworkConfiguration struct { + NetworkInterface string `json:"defaultNetworkInterface,omitempty"` + PermitSlirpInterface *bool `json:"permitSlirpInterface,omitempty"` + PermitBridgeInterfaceOnPodNetwork *bool `json:"permitBridgeInterfaceOnPodNetwork,omitempty"` +} + +// GuestAgentPing configures the guest-agent based ping probe +type GuestAgentPing struct { +} + +type ProfilerResult struct { + PprofData map[string][]byte `json:"pprofData,omitempty"` +} + +type ClusterProfilerResults struct { + ComponentResults map[string]ProfilerResult `json:"componentResults"` + Continue string `json:"continue,omitempty"` +} + +type ClusterProfilerRequest struct { + LabelSelector string `json:"labelSelector,omitempty"` + Continue string `json:"continue,omitempty"` + PageSize int64 `json:"pageSize"` +} + +// FlavorMatcher references a flavor that is used to fill fields in the VMI template. +type FlavorMatcher struct { + // Name is the name of the VirtualMachineFlavor or VirtualMachineClusterFlavor + Name string `json:"name"` + + // Kind specifies which flavor resource is referenced. + // Allowed values are: "VirtualMachineFlavor" and "VirtualMachineClusterFlavor". + // If not specified, "VirtualMachineClusterFlavor" is used by default. + // + // +optional + Kind string `json:"kind,omitempty"` +} + +// PreferenceMatcher references a set of preference that is used to fill fields in the VMI template. +type PreferenceMatcher struct { + // Name is the name of the VirtualMachinePreference or VirtualMachineClusterPreference + Name string `json:"name"` + + // Kind specifies which preference resource is referenced. + // Allowed values are: "VirtualMachinePreference" and "VirtualMachineClusterPreference". + // If not specified, "VirtualMachineClusterPreference" is used by default. + // + // +optional + Kind string `json:"kind,omitempty"` +} diff --git a/vendor/kubevirt.io/api/core/v1/types_swagger_generated.go b/vendor/kubevirt.io/api/core/v1/types_swagger_generated.go new file mode 100644 index 00000000..7049bc71 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/types_swagger_generated.go @@ -0,0 +1,776 @@ +// Code generated by swagger-doc. DO NOT EDIT. + +package v1 + +func (VirtualMachineInstance) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstance is *the* VirtualMachineInstance Definition. It represents a virtual machine in the runtime environment of kubernetes.\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+genclient", + "spec": "VirtualMachineInstance Spec contains the VirtualMachineInstance specification.", + "status": "Status is the high level overview of how the VirtualMachineInstance is doing. It contains information available to controllers and users.", + } +} + +func (VirtualMachineInstanceList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceList is a list of VirtualMachines\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineInstanceSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceSpec is a description of a VirtualMachineInstance.", + "priorityClassName": "If specified, indicates the pod's priority.\nIf not specified, the pod priority will be default or zero if there is no\ndefault.\n+optional", + "domain": "Specification of the desired behavior of the VirtualMachineInstance on the host.", + "nodeSelector": "NodeSelector is a selector which must be true for the vmi to fit on a node.\nSelector which must match a node's labels for the vmi to be scheduled on that node.\nMore info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/\n+optional", + "affinity": "If affinity is specifies, obey all the affinity rules", + "schedulerName": "If specified, the VMI will be dispatched by specified scheduler.\nIf not specified, the VMI will be dispatched by default scheduler.\n+optional", + "tolerations": "If toleration is specified, obey all the toleration rules.", + "evictionStrategy": "EvictionStrategy can be set to \"LiveMigrate\" if the VirtualMachineInstance should be\nmigrated instead of shut-off in case of a node drain.\n\n+optional", + "startStrategy": "StartStrategy can be set to \"Paused\" if Virtual Machine should be started in paused state.\n\n+optional", + "terminationGracePeriodSeconds": "Grace period observed after signalling a VirtualMachineInstance to stop after which the VirtualMachineInstance is force terminated.", + "volumes": "List of volumes that can be mounted by disks belonging to the vmi.", + "livenessProbe": "Periodic probe of VirtualMachineInstance liveness.\nVirtualmachineInstances will be stopped if the probe fails.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes\n+optional", + "readinessProbe": "Periodic probe of VirtualMachineInstance service readiness.\nVirtualmachineInstances will be removed from service endpoints if the probe fails.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes\n+optional", + "hostname": "Specifies the hostname of the vmi\nIf not specified, the hostname will be set to the name of the vmi, if dhcp or cloud-init is configured properly.\n+optional", + "subdomain": "If specified, the fully qualified vmi hostname will be \"...svc.\".\nIf not specified, the vmi will not have a domainname at all. The DNS entry will resolve to the vmi,\nno matter if the vmi itself can pick up a hostname.\n+optional", + "networks": "List of networks that can be attached to a vm's virtual interface.", + "dnsPolicy": "Set DNS policy for the pod.\nDefaults to \"ClusterFirst\".\nValid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'.\nDNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy.\nTo have DNS options set along with hostNetwork, you have to specify DNS policy\nexplicitly to 'ClusterFirstWithHostNet'.\n+optional", + "dnsConfig": "Specifies the DNS parameters of a pod.\nParameters specified here will be merged to the generated DNS\nconfiguration based on DNSPolicy.\n+optional", + "accessCredentials": "Specifies a set of public keys to inject into the vm guest\n+listType=atomic\n+optional", + } +} + +func (VirtualMachineInstancePhaseTransitionTimestamp) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstancePhaseTransitionTimestamp gives a timestamp in relation to when a phase is set on a vmi", + "phase": "Phase is the status of the VirtualMachineInstance in kubernetes world. It is not the VirtualMachineInstance status, but partially correlates to it.", + "phaseTransitionTimestamp": "PhaseTransitionTimestamp is the timestamp of when the phase change occurred", + } +} + +func (TopologyHints) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (VirtualMachineInstanceStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceStatus represents information about the status of a VirtualMachineInstance. Status may trail the actual\nstate of a system.", + "nodeName": "NodeName is the name where the VirtualMachineInstance is currently running.", + "reason": "A brief CamelCase message indicating details about why the VMI is in this state. e.g. 'NodeUnresponsive'\n+optional", + "conditions": "Conditions are specific points in VirtualMachineInstance's pod runtime.", + "phase": "Phase is the status of the VirtualMachineInstance in kubernetes world. It is not the VirtualMachineInstance status, but partially correlates to it.", + "phaseTransitionTimestamps": "PhaseTransitionTimestamp is the timestamp of when the last phase change occurred\n+listType=atomic\n+optional", + "interfaces": "Interfaces represent the details of available network interfaces.", + "guestOSInfo": "Guest OS Information", + "migrationState": "Represents the status of a live migration", + "migrationMethod": "Represents the method using which the vmi can be migrated: live migration or block migration", + "migrationTransport": "This represents the migration transport", + "qosClass": "The Quality of Service (QOS) classification assigned to the virtual machine instance based on resource requirements\nSee PodQOSClass type for available QOS classes\nMore info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md\n+optional", + "launcherContainerImageVersion": "LauncherContainerImageVersion indicates what container image is currently active for the vmi.", + "evacuationNodeName": "EvacuationNodeName is used to track the eviction process of a VMI. It stores the name of the node that we want\nto evacuate. It is meant to be used by KubeVirt core components only and can't be set or modified by users.\n+optional", + "activePods": "ActivePods is a mapping of pod UID to node name.\nIt is possible for multiple pods to be running for a single VMI during migration.", + "volumeStatus": "VolumeStatus contains the statuses of all the volumes\n+optional\n+listType=atomic", + "fsFreezeStatus": "FSFreezeStatus is the state of the fs of the guest\nit can be either frozen or thawed\n+optional", + "topologyHints": "+optional", + "virtualMachineRevisionName": "VirtualMachineRevisionName is used to get the vm revision of the vmi when doing\nan online vm snapshot\n+optional", + "runtimeUser": "RuntimeUser is used to determine what user will be used in launcher\n+optional", + } +} + +func (PersistentVolumeClaimInfo) SwaggerDoc() map[string]string { + return map[string]string{ + "": "PersistentVolumeClaimInfo contains the relavant information virt-handler needs cached about a PVC", + "accessModes": "AccessModes contains the desired access modes the volume should have.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1\n+listType=atomic\n+optional", + "volumeMode": "VolumeMode defines what type of volume is required by the claim.\nValue of Filesystem is implied when not included in claim spec.\n+optional", + "capacity": "Capacity represents the capacity set on the corresponding PVC status\n+optional", + "requests": "Requests represents the resources requested by the corresponding PVC spec\n+optional", + "preallocated": "Preallocated indicates if the PVC's storage is preallocated or not\n+optional", + "filesystemOverhead": "Percentage of filesystem's size to be reserved when resizing the PVC\n+optional", + } +} + +func (VolumeStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VolumeStatus represents information about the status of volumes attached to the VirtualMachineInstance.", + "name": "Name is the name of the volume", + "target": "Target is the target name used when adding the volume to the VM, eg: vda", + "phase": "Phase is the phase", + "reason": "Reason is a brief description of why we are in the current hotplug volume phase", + "message": "Message is a detailed message about the current hotplug volume phase", + "persistentVolumeClaimInfo": "PersistentVolumeClaimInfo is information about the PVC that handler requires during start flow", + "hotplugVolume": "If the volume is hotplug, this will contain the hotplug status.", + "size": "Represents the size of the volume", + "memoryDumpVolume": "If the volume is memorydump volume, this will contain the memorydump info.", + } +} + +func (DomainMemoryDumpInfo) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DomainMemoryDumpInfo represents the memory dump information", + "startTimestamp": "StartTimestamp is the time when the memory dump started", + "endTimestamp": "EndTimestamp is the time when the memory dump completed", + "claimName": "ClaimName is the name of the pvc the memory was dumped to", + "targetFileName": "TargetFileName is the name of the memory dump output", + } +} + +func (HotplugVolumeStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "HotplugVolumeStatus represents the hotplug status of the volume", + "attachPodName": "AttachPodName is the name of the pod used to attach the volume to the node.", + "attachPodUID": "AttachPodUID is the UID of the pod used to attach the volume to the node.", + } +} + +func (VirtualMachineInstanceCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "lastProbeTime": "+nullable", + "lastTransitionTime": "+nullable", + } +} + +func (VirtualMachineInstanceMigrationCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "lastProbeTime": "+nullable", + "lastTransitionTime": "+nullable", + } +} + +func (VirtualMachineInstanceNetworkInterface) SwaggerDoc() map[string]string { + return map[string]string{ + "ipAddress": "IP address of a Virtual Machine interface. It is always the first item of\nIPs", + "mac": "Hardware address of a Virtual Machine interface", + "name": "Name of the interface, corresponds to name of the network assigned to the interface", + "ipAddresses": "List of all IP addresses of a Virtual Machine interface", + "interfaceName": "The interface name inside the Virtual Machine", + "infoSource": "Specifies the origin of the interface data collected. values: domain, guest-agent, or both", + } +} + +func (VirtualMachineInstanceGuestOSInfo) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Name of the Guest OS", + "kernelRelease": "Guest OS Kernel Release", + "version": "Guest OS Version", + "prettyName": "Guest OS Pretty Name", + "versionId": "Version ID of the Guest OS", + "kernelVersion": "Kernel version of the Guest OS", + "machine": "Machine type of the Guest OS", + "id": "Guest OS Id", + } +} + +func (VirtualMachineInstanceMigrationState) SwaggerDoc() map[string]string { + return map[string]string{ + "": "+k8s:openapi-gen=true", + "startTimestamp": "The time the migration action began\n+nullable", + "endTimestamp": "The time the migration action ended\n+nullable", + "targetNodeDomainDetected": "The Target Node has seen the Domain Start Event", + "targetNodeAddress": "The address of the target node to use for the migration", + "targetDirectMigrationNodePorts": "The list of ports opened for live migration on the destination node", + "targetNode": "The target node that the VMI is moving to", + "targetPod": "The target pod that the VMI is moving to", + "targetAttachmentPodUID": "The UID of the target attachment pod for hotplug volumes", + "sourceNode": "The source node that the VMI originated on", + "completed": "Indicates the migration completed", + "failed": "Indicates that the migration failed", + "abortRequested": "Indicates that the migration has been requested to abort", + "abortStatus": "Indicates the final status of the live migration abortion", + "migrationUid": "The VirtualMachineInstanceMigration object associated with this migration", + "mode": "Lets us know if the vmi is currently running pre or post copy migration", + "migrationPolicyName": "Name of the migration policy. If string is empty, no policy is matched", + "migrationConfiguration": "Migration configurations to apply", + "targetCPUSet": "If the VMI requires dedicated CPUs, this field will\nhold the dedicated CPU set on the target node\n+listType=atomic", + "targetNodeTopology": "If the VMI requires dedicated CPUs, this field will\nhold the numa topology on the target node", + } +} + +func (VMISelector) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Name of the VirtualMachineInstance to migrate", + } +} + +func (VirtualMachineInstanceReplicaSet) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstance is *the* VirtualMachineInstance Definition. It represents a virtual machine in the runtime environment of kubernetes.\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+genclient", + "spec": "VirtualMachineInstance Spec contains the VirtualMachineInstance specification.", + "status": "Status is the high level overview of how the VirtualMachineInstance is doing. It contains information available to controllers and users.\n+nullable", + } +} + +func (VirtualMachineInstanceReplicaSetList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VMIList is a list of VMIs\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineInstanceReplicaSetSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "replicas": "Number of desired pods. This is a pointer to distinguish between explicit\nzero and not specified. Defaults to 1.\n+optional", + "selector": "Label selector for pods. Existing ReplicaSets whose pods are\nselected by this will be the ones affected by this deployment.", + "template": "Template describes the pods that will be created.", + "paused": "Indicates that the replica set is paused.\n+optional", + } +} + +func (VirtualMachineInstanceReplicaSetStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "replicas": "Total number of non-terminated pods targeted by this deployment (their labels match the selector).\n+optional", + "readyReplicas": "The number of ready replicas for this replica set.\n+optional", + "labelSelector": "Canonical form of the label selector for HPA which consumes it through the scale subresource.", + } +} + +func (VirtualMachineInstanceReplicaSetCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "lastProbeTime": "+nullable", + "lastTransitionTime": "+nullable", + } +} + +func (DataVolumeTemplateDummyStatus) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (DataVolumeTemplateSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "spec": "DataVolumeSpec contains the DataVolume specification.", + "status": "DataVolumeTemplateDummyStatus is here simply for backwards compatibility with\na previous API.\n+nullable\n+optional", + } +} + +func (VirtualMachineInstanceTemplateSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "metadata": "+kubebuilder:pruning:PreserveUnknownFields\n+nullable", + "spec": "VirtualMachineInstance Spec contains the VirtualMachineInstance specification.", + } +} + +func (VirtualMachineInstanceMigration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceMigration represents the object tracking a VMI's migration\nto another host in the cluster\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+genclient", + } +} + +func (VirtualMachineInstanceMigrationList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceMigrationList is a list of VirtualMachineMigrations\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineInstanceMigrationSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "vmiName": "The name of the VMI to perform the migration on. VMI must exist in the migration objects namespace", + } +} + +func (VirtualMachineInstanceMigrationStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceMigration reprents information pertaining to a VMI's migration.", + } +} + +func (VirtualMachineInstancePreset) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstancePreset defines a VMI spec.domain to be applied to all VMIs that match the provided label selector\nMore info: https://kubevirt.io/user-guide/virtual_machines/presets/#overrides\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+genclient", + "spec": "VirtualMachineInstance Spec contains the VirtualMachineInstance specification.", + } +} + +func (VirtualMachineInstancePresetList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstancePresetList is a list of VirtualMachinePresets\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineInstancePresetSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "selector": "Selector is a label query over a set of VMIs.\nRequired.", + "domain": "Domain is the same object type as contained in VirtualMachineInstanceSpec", + } +} + +func (VirtualMachine) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachine handles the VirtualMachines that are not running\nor are in a stopped state\nThe VirtualMachine contains the template to create the\nVirtualMachineInstance. It also mirrors the running state of the created\nVirtualMachineInstance in its status.\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+genclient", + "spec": "Spec contains the specification of VirtualMachineInstance created", + "status": "Status holds the current state of the controller and brief information\nabout its associated VirtualMachineInstance", + } +} + +func (VirtualMachineList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineList is a list of virtualmachines\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineSpec describes how the proper VirtualMachine\nshould look like", + "running": "Running controls whether the associatied VirtualMachineInstance is created or not\nMutually exclusive with RunStrategy", + "runStrategy": "Running state indicates the requested running state of the VirtualMachineInstance\nmutually exclusive with Running", + "flavor": "FlavorMatcher references a flavor that is used to fill fields in Template", + "preference": "PreferenceMatcher references a set of preference that is used to fill fields in Template", + "template": "Template is the direct specification of VirtualMachineInstance", + "dataVolumeTemplates": "dataVolumeTemplates is a list of dataVolumes that the VirtualMachineInstance template can reference.\nDataVolumes in this list are dynamically created for the VirtualMachine and are tied to the VirtualMachine's life-cycle.", + } +} + +func (VirtualMachineStartFailure) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineStartFailure tracks VMIs which failed to transition successfully\nto running using the VM status", + } +} + +func (VirtualMachineStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineStatus represents the status returned by the\ncontroller to describe how the VirtualMachine is doing", + "snapshotInProgress": "SnapshotInProgress is the name of the VirtualMachineSnapshot currently executing", + "restoreInProgress": "RestoreInProgress is the name of the VirtualMachineRestore currently executing", + "created": "Created indicates if the virtual machine is created in the cluster", + "ready": "Ready indicates if the virtual machine is running and ready", + "printableStatus": "PrintableStatus is a human readable, high-level representation of the status of the virtual machine", + "conditions": "Hold the state information of the VirtualMachine and its VirtualMachineInstance", + "stateChangeRequests": "StateChangeRequests indicates a list of actions that should be taken on a VMI\ne.g. stop a specific VMI then start a new one.", + "volumeRequests": "VolumeRequests indicates a list of volumes add or remove from the VMI template and\nhotplug on an active running VMI.\n+listType=atomic", + "volumeSnapshotStatuses": "VolumeSnapshotStatuses indicates a list of statuses whether snapshotting is\nsupported by each volume.", + "startFailure": "StartFailure tracks consecutive VMI startup failures for the purposes of\ncrash loop backoffs\n+nullable\n+optional", + "memoryDumpRequest": "MemoryDumpRequest tracks memory dump request phase and info of getting a memory\ndump to the given pvc\n+nullable\n+optional", + } +} + +func (VolumeSnapshotStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "name": "Volume name", + "enabled": "True if the volume supports snapshotting", + "reason": "Empty if snapshotting is enabled, contains reason otherwise", + } +} + +func (VirtualMachineVolumeRequest) SwaggerDoc() map[string]string { + return map[string]string{ + "addVolumeOptions": "AddVolumeOptions when set indicates a volume should be added. The details\nwithin this field specify how to add the volume", + "removeVolumeOptions": "RemoveVolumeOptions when set indicates a volume should be removed. The details\nwithin this field specify how to add the volume", + } +} + +func (VirtualMachineStateChangeRequest) SwaggerDoc() map[string]string { + return map[string]string{ + "action": "Indicates the type of action that is requested. e.g. Start or Stop", + "data": "Provides additional data in order to perform the Action", + "uid": "Indicates the UUID of an existing Virtual Machine Instance that this change request applies to -- if applicable", + } +} + +func (VirtualMachineCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineCondition represents the state of VirtualMachine", + "lastProbeTime": "+nullable", + "lastTransitionTime": "+nullable", + } +} + +func (Handler) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Handler defines a specific action that should be taken", + "exec": "One and only one of the following should be specified.\nExec specifies the action to take, it will be executed on the guest through the qemu-guest-agent.\nIf the guest agent is not available, this probe will fail.\n+optional", + "guestAgentPing": "GuestAgentPing contacts the qemu-guest-agent for availability checks.\n+optional", + "httpGet": "HTTPGet specifies the http request to perform.\n+optional", + "tcpSocket": "TCPSocket specifies an action involving a TCP port.\nTCP hooks not yet supported\n+optional", + } +} + +func (Probe) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Probe describes a health check to be performed against a VirtualMachineInstance to determine whether it is\nalive or ready to receive traffic.", + "initialDelaySeconds": "Number of seconds after the VirtualMachineInstance has started before liveness probes are initiated.\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes\n+optional", + "timeoutSeconds": "Number of seconds after which the probe times out.\nFor exec probes the timeout fails the probe but does not terminate the command running on the guest.\nThis means a blocking command can result in an increasing load on the guest.\nA small buffer will be added to the resulting workload exec probe to compensate for delays\ncaused by the qemu guest exec mechanism.\nDefaults to 1 second. Minimum value is 1.\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes\n+optional", + "periodSeconds": "How often (in seconds) to perform the probe.\nDefault to 10 seconds. Minimum value is 1.\n+optional", + "successThreshold": "Minimum consecutive successes for the probe to be considered successful after having failed.\nDefaults to 1. Must be 1 for liveness. Minimum value is 1.\n+optional", + "failureThreshold": "Minimum consecutive failures for the probe to be considered failed after having succeeded.\nDefaults to 3. Minimum value is 1.\n+optional", + } +} + +func (KubeVirt) SwaggerDoc() map[string]string { + return map[string]string{ + "": "KubeVirt represents the object deploying all KubeVirt resources\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+genclient", + } +} + +func (KubeVirtList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "KubeVirtList is a list of KubeVirts\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (KubeVirtSelfSignConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "caRotateInterval": "Deprecated. Use CA.Duration instead", + "certRotateInterval": "Deprecated. Use Server.Duration instead", + "caOverlapInterval": "Deprecated. Use CA.Duration and CA.RenewBefore instead", + "ca": "CA configuration\nCA certs are kept in the CA bundle as long as they are valid", + "server": "Server configuration\nCerts are rotated and discarded", + } +} + +func (CertConfig) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CertConfig contains the tunables for TLS certificates", + "duration": "The requested 'duration' (i.e. lifetime) of the Certificate.", + "renewBefore": "The amount of time before the currently issued certificate's \"notAfter\"\ntime that we will begin to attempt to renew the certificate.", + } +} + +func (KubeVirtCertificateRotateStrategy) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (KubeVirtWorkloadUpdateStrategy) SwaggerDoc() map[string]string { + return map[string]string{ + "": "KubeVirtWorkloadUpdateStrategy defines options related to updating a KubeVirt install", + "workloadUpdateMethods": "WorkloadUpdateMethods defines the methods that can be used to disrupt workloads\nduring automated workload updates.\nWhen multiple methods are present, the least disruptive method takes\nprecedence over more disruptive methods. For example if both LiveMigrate and Shutdown\nmethods are listed, only VMs which are not live migratable will be restarted/shutdown\n\nAn empty list defaults to no automated workload updating\n\n+listType=atomic\n+optional", + "batchEvictionSize": "BatchEvictionSize Represents the number of VMIs that can be forced updated per\nthe BatchShutdownInteral interval\n\nDefaults to 10\n\n+optional", + "batchEvictionInterval": "BatchEvictionInterval Represents the interval to wait before issuing the next\nbatch of shutdowns\n\nDefaults to 1 minute\n\n+optional", + } +} + +func (KubeVirtSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "imageTag": "The image tag to use for the continer images installed.\nDefaults to the same tag as the operator's container image.", + "imageRegistry": "The image registry to pull the container images from\nDefaults to the same registry the operator's container image is pulled from.", + "imagePullPolicy": "The ImagePullPolicy to use.", + "monitorNamespace": "The namespace Prometheus is deployed in\nDefaults to openshift-monitor", + "serviceMonitorNamespace": "The namespace the service monitor will be deployed\n When ServiceMonitorNamespace is set, then we'll install the service monitor object in that namespace\notherwise we will use the monitoring namespace.", + "monitorAccount": "The name of the Prometheus service account that needs read-access to KubeVirt endpoints\nDefaults to prometheus-k8s", + "workloadUpdateStrategy": "WorkloadUpdateStrategy defines at the cluster level how to handle\nautomated workload updates", + "uninstallStrategy": "Specifies if kubevirt can be deleted if workloads are still present.\nThis is mainly a precaution to avoid accidental data loss", + "productVersion": "Designate the apps.kubevirt.io/version label for KubeVirt components.\nUseful if KubeVirt is included as part of a product.\nIf ProductVersion is not specified, KubeVirt's version will be used.", + "productName": "Designate the apps.kubevirt.io/part-of label for KubeVirt components.\nUseful if KubeVirt is included as part of a product.\nIf ProductName is not specified, the part-of label will be omitted.", + "productComponent": "Designate the apps.kubevirt.io/component label for KubeVirt components.\nUseful if KubeVirt is included as part of a product.\nIf ProductComponent is not specified, the component label default value is kubevirt.", + "configuration": "holds kubevirt configurations.\nsame as the virt-configMap", + "infra": "selectors and tolerations that should apply to KubeVirt infrastructure components\n+optional", + "workloads": "selectors and tolerations that should apply to KubeVirt workloads\n+optional", + } +} + +func (CustomizeComponents) SwaggerDoc() map[string]string { + return map[string]string{ + "patches": "+listType=atomic", + "flags": "Configure the value used for deployment and daemonset resources", + } +} + +func (Flags) SwaggerDoc() map[string]string { + return map[string]string{ + "": "Flags will create a patch that will replace all flags for the container's\ncommand field. The only flags that will be used are those define. There are no\nguarantees around forward/backward compatibility. If set incorrectly this will\ncause the resource when rolled out to error until flags are updated.", + } +} + +func (CustomizeComponentsPatch) SwaggerDoc() map[string]string { + return map[string]string{ + "resourceName": "+kubebuilder:validation:MinLength=1", + "resourceType": "+kubebuilder:validation:MinLength=1", + } +} + +func (GenerationStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "GenerationStatus keeps track of the generation for a given resource so that decisions about forced updates can be made.", + "group": "group is the group of the thing you're tracking", + "resource": "resource is the resource type of the thing you're tracking", + "namespace": "namespace is where the thing you're tracking is\n+optional", + "name": "name is the name of the thing you're tracking", + "lastGeneration": "lastGeneration is the last generation of the workload controller involved", + "hash": "hash is an optional field set for resources without generation that are content sensitive like secrets and configmaps\n+optional", + } +} + +func (KubeVirtStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "KubeVirtStatus represents information pertaining to a KubeVirt deployment.", + "generations": "+listType=atomic", + } +} + +func (KubeVirtCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "": "KubeVirtCondition represents a condition of a KubeVirt deployment", + "lastProbeTime": "+optional\n+nullable", + "lastTransitionTime": "+optional\n+nullable", + } +} + +func (RestartOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "RestartOptions may be provided when deleting an API object.", + "gracePeriodSeconds": "The duration in seconds before the object should be force-restarted. Value must be non-negative integer.\nThe value zero indicates, restart immediately. If this value is nil, the default grace period for deletion of the corresponding VMI for the\nspecified type will be used to determine on how much time to give the VMI to restart.\nDefaults to a per object value if not specified. zero means restart immediately.\nAllowed Values: nil and 0\n+optional", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (StartOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StartOptions may be provided on start request.", + "paused": "Indicates that VM will be started in paused state.\n+optional", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (PauseOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "PauseOptions may be provided on pause request.", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (UnpauseOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "UnpauseOptions may be provided on unpause request.", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (StopOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StopOptions may be provided when deleting an API object.", + "gracePeriod": "this updates the VMIs terminationGracePeriodSeconds during shutdown\n+optional", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (MigrateOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "MigrateOptions may be provided on migrate request.", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (VirtualMachineInstanceGuestAgentInfo) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceGuestAgentInfo represents information from the installed guest agent\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "guestAgentVersion": "GAVersion is a version of currently installed guest agent", + "supportedCommands": "Return command list the guest agent supports\n+listType=atomic", + "hostname": "Hostname represents FQDN of a guest", + "os": "OS contains the guest operating system information", + "timezone": "Timezone is guest os current timezone", + "userList": "UserList is a list of active guest OS users", + "fsInfo": "FSInfo is a guest os filesystem information containing the disk mapping and disk mounts with usage", + "fsFreezeStatus": "FSFreezeStatus is the state of the fs of the guest\nit can be either frozen or thawed", + } +} + +func (GuestAgentCommandInfo) SwaggerDoc() map[string]string { + return map[string]string{ + "": "List of commands that QEMU guest agent supports", + } +} + +func (VirtualMachineInstanceGuestOSUserList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceGuestOSUserList comprises the list of all active users on guest machine\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineInstanceGuestOSUser) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineGuestOSUser is the single user of the guest os", + } +} + +func (VirtualMachineInstanceFileSystemInfo) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceFileSystemInfo represents information regarding single guest os filesystem", + } +} + +func (VirtualMachineInstanceFileSystemList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceFileSystemList comprises the list of all filesystems on guest machine\n\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + } +} + +func (VirtualMachineInstanceFileSystem) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineInstanceFileSystem represents guest os disk", + } +} + +func (FreezeUnfreezeTimeout) SwaggerDoc() map[string]string { + return map[string]string{ + "": "FreezeUnfreezeTimeout represent the time unfreeze will be triggered if guest was not unfrozen by unfreeze command", + } +} + +func (VirtualMachineMemoryDumpRequest) SwaggerDoc() map[string]string { + return map[string]string{ + "": "VirtualMachineMemoryDumpRequest represent the memory dump request phase and info", + "claimName": "ClaimName is the name of the pvc that will contain the memory dump", + "phase": "Phase represents the memory dump phase", + "startTimestamp": "StartTimestamp represents the time the memory dump started", + "endTimestamp": "EndTimestamp represents the time the memory dump was completed", + "fileName": "FileName represents the name of the output file", + "message": "Message is a detailed message about failure of the memory dump", + } +} + +func (AddVolumeOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "AddVolumeOptions is provided when dynamically hot plugging a volume and disk", + "name": "Name represents the name that will be used to map the\ndisk to the corresponding volume. This overrides any name\nset inside the Disk struct itself.", + "disk": "Disk represents the hotplug disk that will be plugged into the running VMI", + "volumeSource": "VolumeSource represents the source of the volume to map to the disk.", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (RemoveVolumeOptions) SwaggerDoc() map[string]string { + return map[string]string{ + "": "RemoveVolumeOptions is provided when dynamically hot unplugging volume and disk", + "name": "Name represents the name that maps to both the disk and volume that\nshould be removed", + "dryRun": "When present, indicates that modifications should not be\npersisted. An invalid or unrecognized dryRun directive will\nresult in an error response and no further processing of the\nrequest. Valid values are:\n- All: all dry run stages will be processed\n+optional\n+listType=atomic", + } +} + +func (TokenBucketRateLimiter) SwaggerDoc() map[string]string { + return map[string]string{ + "qps": "QPS indicates the maximum QPS to the apiserver from this client.\nIf it's zero, the component default will be used", + "burst": "Maximum burst for throttle.\nIf it's zero, the component default will be used", + } +} + +func (RateLimiter) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (RESTClientConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "RESTClientConfiguration allows configuring certain aspects of the k8s rest client.", + "rateLimiter": "RateLimiter allows selecting and configuring different rate limiters for the k8s client.", + } +} + +func (ReloadableComponentConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ReloadableComponentConfiguration holds all generic k8s configuration options which can\nbe reloaded by components without requiring a restart.", + "restClient": "RestClient can be used to tune certain aspects of the k8s client in use.", + } +} + +func (KubeVirtConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "KubeVirtConfiguration holds all kubevirt configurations", + "evictionStrategy": "EvictionStrategy defines at the cluster level if the VirtualMachineInstance should be\nmigrated instead of shut-off in case of a node drain. If the VirtualMachineInstance specific\nfield is set it overrides the cluster level one.", + "supportedGuestAgentVersions": "deprecated", + } +} + +func (SMBiosConfiguration) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (MigrationConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "MigrationConfiguration holds migration options", + } +} + +func (DiskVerification) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DiskVerification holds container disks verification limits", + } +} + +func (DeveloperConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DeveloperConfiguration holds developer options", + "useEmulation": "UseEmulation can be set to true to allow fallback to software emulation\nin case hardware-assisted emulation is not available.", + "minimumClusterTSCFrequency": "Allow overriding the automatically determined minimum TSC frequency of the cluster\nand fixate the minimum to this frequency.", + } +} + +func (LogVerbosity) SwaggerDoc() map[string]string { + return map[string]string{ + "": "LogVerbosity sets log verbosity level of various components", + "nodeVerbosity": "NodeVerbosity represents a map of nodes with a specific verbosity level", + } +} + +func (PermittedHostDevices) SwaggerDoc() map[string]string { + return map[string]string{ + "": "PermittedHostDevices holds information about devices allowed for passthrough", + "pciHostDevices": "+listType=atomic", + "mediatedDevices": "+listType=atomic", + } +} + +func (PciHostDevice) SwaggerDoc() map[string]string { + return map[string]string{ + "": "PciHostDevice represents a host PCI device allowed for passthrough", + "pciVendorSelector": "The vendor_id:product_id tuple of the PCI device", + "resourceName": "The name of the resource that is representing the device. Exposed by\na device plugin and requested by VMs. Typically of the form\nvendor.com/product_nameThe name of the resource that is representing\nthe device. Exposed by a device plugin and requested by VMs.\nTypically of the form vendor.com/product_name", + "externalResourceProvider": "If true, KubeVirt will leave the allocation and monitoring to an\nexternal device plugin", + } +} + +func (MediatedHostDevice) SwaggerDoc() map[string]string { + return map[string]string{ + "": "MediatedHostDevice represents a host mediated device allowed for passthrough", + } +} + +func (MediatedDevicesConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "MediatedDevicesConfiguration holds information about MDEV types to be defined, if available", + "mediatedDevicesTypes": "+listType=atomic", + "nodeMediatedDeviceTypes": "+optional\n+listType=atomic", + } +} + +func (NodeMediatedDeviceTypesConfig) SwaggerDoc() map[string]string { + return map[string]string{ + "": "NodeMediatedDeviceTypesConfig holds information about MDEV types to be defined in a specifc node that matches the NodeSelector field.\n+k8s:openapi-gen=true", + "nodeSelector": "NodeSelector is a selector which must be true for the vmi to fit on a node.\nSelector which must match a node's labels for the vmi to be scheduled on that node.\nMore info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", + "mediatedDevicesTypes": "+listType=atomic", + } +} + +func (NetworkConfiguration) SwaggerDoc() map[string]string { + return map[string]string{ + "": "NetworkConfiguration holds network options", + } +} + +func (GuestAgentPing) SwaggerDoc() map[string]string { + return map[string]string{ + "": "GuestAgentPing configures the guest-agent based ping probe", + } +} + +func (ProfilerResult) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (ClusterProfilerResults) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (ClusterProfilerRequest) SwaggerDoc() map[string]string { + return map[string]string{} +} + +func (FlavorMatcher) SwaggerDoc() map[string]string { + return map[string]string{ + "": "FlavorMatcher references a flavor that is used to fill fields in the VMI template.", + "name": "Name is the name of the VirtualMachineFlavor or VirtualMachineClusterFlavor", + "kind": "Kind specifies which flavor resource is referenced.\nAllowed values are: \"VirtualMachineFlavor\" and \"VirtualMachineClusterFlavor\".\nIf not specified, \"VirtualMachineClusterFlavor\" is used by default.\n\n+optional", + } +} + +func (PreferenceMatcher) SwaggerDoc() map[string]string { + return map[string]string{ + "": "PreferenceMatcher references a set of preference that is used to fill fields in the VMI template.", + "name": "Name is the name of the VirtualMachinePreference or VirtualMachineClusterPreference", + "kind": "Kind specifies which preference resource is referenced.\nAllowed values are: \"VirtualMachinePreference\" and \"VirtualMachineClusterPreference\".\nIf not specified, \"VirtualMachineClusterPreference\" is used by default.\n\n+optional", + } +} diff --git a/vendor/kubevirt.io/api/core/v1/zz_generated.defaults.go b/vendor/kubevirt.io/api/core/v1/zz_generated.defaults.go new file mode 100644 index 00000000..b3f65406 --- /dev/null +++ b/vendor/kubevirt.io/api/core/v1/zz_generated.defaults.go @@ -0,0 +1,566 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2022 The KubeVirt Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&VirtualMachine{}, func(obj interface{}) { SetObjectDefaults_VirtualMachine(obj.(*VirtualMachine)) }) + scheme.AddTypeDefaultingFunc(&VirtualMachineInstance{}, func(obj interface{}) { SetObjectDefaults_VirtualMachineInstance(obj.(*VirtualMachineInstance)) }) + scheme.AddTypeDefaultingFunc(&VirtualMachineInstanceList{}, func(obj interface{}) { SetObjectDefaults_VirtualMachineInstanceList(obj.(*VirtualMachineInstanceList)) }) + scheme.AddTypeDefaultingFunc(&VirtualMachineInstancePreset{}, func(obj interface{}) { + SetObjectDefaults_VirtualMachineInstancePreset(obj.(*VirtualMachineInstancePreset)) + }) + scheme.AddTypeDefaultingFunc(&VirtualMachineInstancePresetList{}, func(obj interface{}) { + SetObjectDefaults_VirtualMachineInstancePresetList(obj.(*VirtualMachineInstancePresetList)) + }) + scheme.AddTypeDefaultingFunc(&VirtualMachineInstanceReplicaSet{}, func(obj interface{}) { + SetObjectDefaults_VirtualMachineInstanceReplicaSet(obj.(*VirtualMachineInstanceReplicaSet)) + }) + scheme.AddTypeDefaultingFunc(&VirtualMachineInstanceReplicaSetList{}, func(obj interface{}) { + SetObjectDefaults_VirtualMachineInstanceReplicaSetList(obj.(*VirtualMachineInstanceReplicaSetList)) + }) + scheme.AddTypeDefaultingFunc(&VirtualMachineList{}, func(obj interface{}) { SetObjectDefaults_VirtualMachineList(obj.(*VirtualMachineList)) }) + return nil +} + +func SetObjectDefaults_VirtualMachine(in *VirtualMachine) { + if in.Spec.Template != nil { + if in.Spec.Template.Spec.Domain.Firmware != nil { + SetDefaults_Firmware(in.Spec.Template.Spec.Domain.Firmware) + } + if in.Spec.Template.Spec.Domain.Clock != nil { + if in.Spec.Template.Spec.Domain.Clock.Timer != nil { + if in.Spec.Template.Spec.Domain.Clock.Timer.HPET != nil { + SetDefaults_HPETTimer(in.Spec.Template.Spec.Domain.Clock.Timer.HPET) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.KVM != nil { + SetDefaults_KVMTimer(in.Spec.Template.Spec.Domain.Clock.Timer.KVM) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.PIT != nil { + SetDefaults_PITTimer(in.Spec.Template.Spec.Domain.Clock.Timer.PIT) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.RTC != nil { + SetDefaults_RTCTimer(in.Spec.Template.Spec.Domain.Clock.Timer.RTC) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.Hyperv != nil { + SetDefaults_HypervTimer(in.Spec.Template.Spec.Domain.Clock.Timer.Hyperv) + } + } + } + if in.Spec.Template.Spec.Domain.Features != nil { + SetDefaults_FeatureState(&in.Spec.Template.Spec.Domain.Features.ACPI) + if in.Spec.Template.Spec.Domain.Features.APIC != nil { + SetDefaults_FeatureAPIC(in.Spec.Template.Spec.Domain.Features.APIC) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv != nil { + if in.Spec.Template.Spec.Domain.Features.Hyperv.Relaxed != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Relaxed) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.VAPIC != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.VAPIC) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Spinlocks != nil { + SetDefaults_FeatureSpinlocks(in.Spec.Template.Spec.Domain.Features.Hyperv.Spinlocks) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.VPIndex != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.VPIndex) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Runtime != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Runtime) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.SyNIC != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.SyNIC) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer != nil { + SetDefaults_SyNICTimer(in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer) + if in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer.Direct != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer.Direct) + } + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Reset != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Reset) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.VendorID != nil { + SetDefaults_FeatureVendorID(in.Spec.Template.Spec.Domain.Features.Hyperv.VendorID) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Frequencies != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Frequencies) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Reenlightenment != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Reenlightenment) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.TLBFlush != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.TLBFlush) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.IPI != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.IPI) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.EVMCS != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.EVMCS) + } + } + if in.Spec.Template.Spec.Domain.Features.SMM != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.SMM) + } + if in.Spec.Template.Spec.Domain.Features.Pvspinlock != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Pvspinlock) + } + } + for i := range in.Spec.Template.Spec.Domain.Devices.Disks { + a := &in.Spec.Template.Spec.Domain.Devices.Disks[i] + SetDefaults_DiskDevice(&a.DiskDevice) + if a.DiskDevice.CDRom != nil { + SetDefaults_CDRomTarget(a.DiskDevice.CDRom) + } + if a.BlockSize != nil { + if a.BlockSize.MatchVolume != nil { + SetDefaults_FeatureState(a.BlockSize.MatchVolume) + } + } + } + if in.Spec.Template.Spec.Domain.Devices.Watchdog != nil { + SetDefaults_Watchdog(in.Spec.Template.Spec.Domain.Devices.Watchdog) + if in.Spec.Template.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB != nil { + SetDefaults_I6300ESBWatchdog(in.Spec.Template.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB) + } + } + for i := range in.Spec.Template.Spec.Domain.Devices.GPUs { + a := &in.Spec.Template.Spec.Domain.Devices.GPUs[i] + if a.VirtualGPUOptions != nil { + if a.VirtualGPUOptions.Display != nil { + if a.VirtualGPUOptions.Display.RamFB != nil { + SetDefaults_FeatureState(a.VirtualGPUOptions.Display.RamFB) + } + } + } + } + if in.Spec.Template.Spec.LivenessProbe != nil { + SetDefaults_Probe(in.Spec.Template.Spec.LivenessProbe) + } + if in.Spec.Template.Spec.ReadinessProbe != nil { + SetDefaults_Probe(in.Spec.Template.Spec.ReadinessProbe) + } + } + for i := range in.Status.VolumeRequests { + a := &in.Status.VolumeRequests[i] + if a.AddVolumeOptions != nil { + if a.AddVolumeOptions.Disk != nil { + SetDefaults_DiskDevice(&a.AddVolumeOptions.Disk.DiskDevice) + if a.AddVolumeOptions.Disk.DiskDevice.CDRom != nil { + SetDefaults_CDRomTarget(a.AddVolumeOptions.Disk.DiskDevice.CDRom) + } + if a.AddVolumeOptions.Disk.BlockSize != nil { + if a.AddVolumeOptions.Disk.BlockSize.MatchVolume != nil { + SetDefaults_FeatureState(a.AddVolumeOptions.Disk.BlockSize.MatchVolume) + } + } + } + } + } +} + +func SetObjectDefaults_VirtualMachineInstance(in *VirtualMachineInstance) { + SetDefaults_VirtualMachineInstance(in) + if in.Spec.Domain.Firmware != nil { + SetDefaults_Firmware(in.Spec.Domain.Firmware) + } + if in.Spec.Domain.Clock != nil { + if in.Spec.Domain.Clock.Timer != nil { + if in.Spec.Domain.Clock.Timer.HPET != nil { + SetDefaults_HPETTimer(in.Spec.Domain.Clock.Timer.HPET) + } + if in.Spec.Domain.Clock.Timer.KVM != nil { + SetDefaults_KVMTimer(in.Spec.Domain.Clock.Timer.KVM) + } + if in.Spec.Domain.Clock.Timer.PIT != nil { + SetDefaults_PITTimer(in.Spec.Domain.Clock.Timer.PIT) + } + if in.Spec.Domain.Clock.Timer.RTC != nil { + SetDefaults_RTCTimer(in.Spec.Domain.Clock.Timer.RTC) + } + if in.Spec.Domain.Clock.Timer.Hyperv != nil { + SetDefaults_HypervTimer(in.Spec.Domain.Clock.Timer.Hyperv) + } + } + } + if in.Spec.Domain.Features != nil { + SetDefaults_FeatureState(&in.Spec.Domain.Features.ACPI) + if in.Spec.Domain.Features.APIC != nil { + SetDefaults_FeatureAPIC(in.Spec.Domain.Features.APIC) + } + if in.Spec.Domain.Features.Hyperv != nil { + if in.Spec.Domain.Features.Hyperv.Relaxed != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Relaxed) + } + if in.Spec.Domain.Features.Hyperv.VAPIC != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.VAPIC) + } + if in.Spec.Domain.Features.Hyperv.Spinlocks != nil { + SetDefaults_FeatureSpinlocks(in.Spec.Domain.Features.Hyperv.Spinlocks) + } + if in.Spec.Domain.Features.Hyperv.VPIndex != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.VPIndex) + } + if in.Spec.Domain.Features.Hyperv.Runtime != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Runtime) + } + if in.Spec.Domain.Features.Hyperv.SyNIC != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.SyNIC) + } + if in.Spec.Domain.Features.Hyperv.SyNICTimer != nil { + SetDefaults_SyNICTimer(in.Spec.Domain.Features.Hyperv.SyNICTimer) + if in.Spec.Domain.Features.Hyperv.SyNICTimer.Direct != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.SyNICTimer.Direct) + } + } + if in.Spec.Domain.Features.Hyperv.Reset != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Reset) + } + if in.Spec.Domain.Features.Hyperv.VendorID != nil { + SetDefaults_FeatureVendorID(in.Spec.Domain.Features.Hyperv.VendorID) + } + if in.Spec.Domain.Features.Hyperv.Frequencies != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Frequencies) + } + if in.Spec.Domain.Features.Hyperv.Reenlightenment != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Reenlightenment) + } + if in.Spec.Domain.Features.Hyperv.TLBFlush != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.TLBFlush) + } + if in.Spec.Domain.Features.Hyperv.IPI != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.IPI) + } + if in.Spec.Domain.Features.Hyperv.EVMCS != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.EVMCS) + } + } + if in.Spec.Domain.Features.SMM != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.SMM) + } + if in.Spec.Domain.Features.Pvspinlock != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Pvspinlock) + } + } + for i := range in.Spec.Domain.Devices.Disks { + a := &in.Spec.Domain.Devices.Disks[i] + SetDefaults_DiskDevice(&a.DiskDevice) + if a.DiskDevice.CDRom != nil { + SetDefaults_CDRomTarget(a.DiskDevice.CDRom) + } + if a.BlockSize != nil { + if a.BlockSize.MatchVolume != nil { + SetDefaults_FeatureState(a.BlockSize.MatchVolume) + } + } + } + if in.Spec.Domain.Devices.Watchdog != nil { + SetDefaults_Watchdog(in.Spec.Domain.Devices.Watchdog) + if in.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB != nil { + SetDefaults_I6300ESBWatchdog(in.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB) + } + } + for i := range in.Spec.Domain.Devices.GPUs { + a := &in.Spec.Domain.Devices.GPUs[i] + if a.VirtualGPUOptions != nil { + if a.VirtualGPUOptions.Display != nil { + if a.VirtualGPUOptions.Display.RamFB != nil { + SetDefaults_FeatureState(a.VirtualGPUOptions.Display.RamFB) + } + } + } + } + if in.Spec.LivenessProbe != nil { + SetDefaults_Probe(in.Spec.LivenessProbe) + } + if in.Spec.ReadinessProbe != nil { + SetDefaults_Probe(in.Spec.ReadinessProbe) + } +} + +func SetObjectDefaults_VirtualMachineInstanceList(in *VirtualMachineInstanceList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_VirtualMachineInstance(a) + } +} + +func SetObjectDefaults_VirtualMachineInstancePreset(in *VirtualMachineInstancePreset) { + if in.Spec.Domain != nil { + if in.Spec.Domain.Firmware != nil { + SetDefaults_Firmware(in.Spec.Domain.Firmware) + } + if in.Spec.Domain.Clock != nil { + if in.Spec.Domain.Clock.Timer != nil { + if in.Spec.Domain.Clock.Timer.HPET != nil { + SetDefaults_HPETTimer(in.Spec.Domain.Clock.Timer.HPET) + } + if in.Spec.Domain.Clock.Timer.KVM != nil { + SetDefaults_KVMTimer(in.Spec.Domain.Clock.Timer.KVM) + } + if in.Spec.Domain.Clock.Timer.PIT != nil { + SetDefaults_PITTimer(in.Spec.Domain.Clock.Timer.PIT) + } + if in.Spec.Domain.Clock.Timer.RTC != nil { + SetDefaults_RTCTimer(in.Spec.Domain.Clock.Timer.RTC) + } + if in.Spec.Domain.Clock.Timer.Hyperv != nil { + SetDefaults_HypervTimer(in.Spec.Domain.Clock.Timer.Hyperv) + } + } + } + if in.Spec.Domain.Features != nil { + SetDefaults_FeatureState(&in.Spec.Domain.Features.ACPI) + if in.Spec.Domain.Features.APIC != nil { + SetDefaults_FeatureAPIC(in.Spec.Domain.Features.APIC) + } + if in.Spec.Domain.Features.Hyperv != nil { + if in.Spec.Domain.Features.Hyperv.Relaxed != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Relaxed) + } + if in.Spec.Domain.Features.Hyperv.VAPIC != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.VAPIC) + } + if in.Spec.Domain.Features.Hyperv.Spinlocks != nil { + SetDefaults_FeatureSpinlocks(in.Spec.Domain.Features.Hyperv.Spinlocks) + } + if in.Spec.Domain.Features.Hyperv.VPIndex != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.VPIndex) + } + if in.Spec.Domain.Features.Hyperv.Runtime != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Runtime) + } + if in.Spec.Domain.Features.Hyperv.SyNIC != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.SyNIC) + } + if in.Spec.Domain.Features.Hyperv.SyNICTimer != nil { + SetDefaults_SyNICTimer(in.Spec.Domain.Features.Hyperv.SyNICTimer) + if in.Spec.Domain.Features.Hyperv.SyNICTimer.Direct != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.SyNICTimer.Direct) + } + } + if in.Spec.Domain.Features.Hyperv.Reset != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Reset) + } + if in.Spec.Domain.Features.Hyperv.VendorID != nil { + SetDefaults_FeatureVendorID(in.Spec.Domain.Features.Hyperv.VendorID) + } + if in.Spec.Domain.Features.Hyperv.Frequencies != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Frequencies) + } + if in.Spec.Domain.Features.Hyperv.Reenlightenment != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.Reenlightenment) + } + if in.Spec.Domain.Features.Hyperv.TLBFlush != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.TLBFlush) + } + if in.Spec.Domain.Features.Hyperv.IPI != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.IPI) + } + if in.Spec.Domain.Features.Hyperv.EVMCS != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Hyperv.EVMCS) + } + } + if in.Spec.Domain.Features.SMM != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.SMM) + } + if in.Spec.Domain.Features.Pvspinlock != nil { + SetDefaults_FeatureState(in.Spec.Domain.Features.Pvspinlock) + } + } + for i := range in.Spec.Domain.Devices.Disks { + a := &in.Spec.Domain.Devices.Disks[i] + SetDefaults_DiskDevice(&a.DiskDevice) + if a.DiskDevice.CDRom != nil { + SetDefaults_CDRomTarget(a.DiskDevice.CDRom) + } + if a.BlockSize != nil { + if a.BlockSize.MatchVolume != nil { + SetDefaults_FeatureState(a.BlockSize.MatchVolume) + } + } + } + if in.Spec.Domain.Devices.Watchdog != nil { + SetDefaults_Watchdog(in.Spec.Domain.Devices.Watchdog) + if in.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB != nil { + SetDefaults_I6300ESBWatchdog(in.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB) + } + } + for i := range in.Spec.Domain.Devices.GPUs { + a := &in.Spec.Domain.Devices.GPUs[i] + if a.VirtualGPUOptions != nil { + if a.VirtualGPUOptions.Display != nil { + if a.VirtualGPUOptions.Display.RamFB != nil { + SetDefaults_FeatureState(a.VirtualGPUOptions.Display.RamFB) + } + } + } + } + } +} + +func SetObjectDefaults_VirtualMachineInstancePresetList(in *VirtualMachineInstancePresetList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_VirtualMachineInstancePreset(a) + } +} + +func SetObjectDefaults_VirtualMachineInstanceReplicaSet(in *VirtualMachineInstanceReplicaSet) { + if in.Spec.Template != nil { + if in.Spec.Template.Spec.Domain.Firmware != nil { + SetDefaults_Firmware(in.Spec.Template.Spec.Domain.Firmware) + } + if in.Spec.Template.Spec.Domain.Clock != nil { + if in.Spec.Template.Spec.Domain.Clock.Timer != nil { + if in.Spec.Template.Spec.Domain.Clock.Timer.HPET != nil { + SetDefaults_HPETTimer(in.Spec.Template.Spec.Domain.Clock.Timer.HPET) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.KVM != nil { + SetDefaults_KVMTimer(in.Spec.Template.Spec.Domain.Clock.Timer.KVM) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.PIT != nil { + SetDefaults_PITTimer(in.Spec.Template.Spec.Domain.Clock.Timer.PIT) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.RTC != nil { + SetDefaults_RTCTimer(in.Spec.Template.Spec.Domain.Clock.Timer.RTC) + } + if in.Spec.Template.Spec.Domain.Clock.Timer.Hyperv != nil { + SetDefaults_HypervTimer(in.Spec.Template.Spec.Domain.Clock.Timer.Hyperv) + } + } + } + if in.Spec.Template.Spec.Domain.Features != nil { + SetDefaults_FeatureState(&in.Spec.Template.Spec.Domain.Features.ACPI) + if in.Spec.Template.Spec.Domain.Features.APIC != nil { + SetDefaults_FeatureAPIC(in.Spec.Template.Spec.Domain.Features.APIC) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv != nil { + if in.Spec.Template.Spec.Domain.Features.Hyperv.Relaxed != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Relaxed) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.VAPIC != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.VAPIC) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Spinlocks != nil { + SetDefaults_FeatureSpinlocks(in.Spec.Template.Spec.Domain.Features.Hyperv.Spinlocks) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.VPIndex != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.VPIndex) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Runtime != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Runtime) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.SyNIC != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.SyNIC) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer != nil { + SetDefaults_SyNICTimer(in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer) + if in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer.Direct != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.SyNICTimer.Direct) + } + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Reset != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Reset) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.VendorID != nil { + SetDefaults_FeatureVendorID(in.Spec.Template.Spec.Domain.Features.Hyperv.VendorID) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Frequencies != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Frequencies) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.Reenlightenment != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.Reenlightenment) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.TLBFlush != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.TLBFlush) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.IPI != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.IPI) + } + if in.Spec.Template.Spec.Domain.Features.Hyperv.EVMCS != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Hyperv.EVMCS) + } + } + if in.Spec.Template.Spec.Domain.Features.SMM != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.SMM) + } + if in.Spec.Template.Spec.Domain.Features.Pvspinlock != nil { + SetDefaults_FeatureState(in.Spec.Template.Spec.Domain.Features.Pvspinlock) + } + } + for i := range in.Spec.Template.Spec.Domain.Devices.Disks { + a := &in.Spec.Template.Spec.Domain.Devices.Disks[i] + SetDefaults_DiskDevice(&a.DiskDevice) + if a.DiskDevice.CDRom != nil { + SetDefaults_CDRomTarget(a.DiskDevice.CDRom) + } + if a.BlockSize != nil { + if a.BlockSize.MatchVolume != nil { + SetDefaults_FeatureState(a.BlockSize.MatchVolume) + } + } + } + if in.Spec.Template.Spec.Domain.Devices.Watchdog != nil { + SetDefaults_Watchdog(in.Spec.Template.Spec.Domain.Devices.Watchdog) + if in.Spec.Template.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB != nil { + SetDefaults_I6300ESBWatchdog(in.Spec.Template.Spec.Domain.Devices.Watchdog.WatchdogDevice.I6300ESB) + } + } + for i := range in.Spec.Template.Spec.Domain.Devices.GPUs { + a := &in.Spec.Template.Spec.Domain.Devices.GPUs[i] + if a.VirtualGPUOptions != nil { + if a.VirtualGPUOptions.Display != nil { + if a.VirtualGPUOptions.Display.RamFB != nil { + SetDefaults_FeatureState(a.VirtualGPUOptions.Display.RamFB) + } + } + } + } + if in.Spec.Template.Spec.LivenessProbe != nil { + SetDefaults_Probe(in.Spec.Template.Spec.LivenessProbe) + } + if in.Spec.Template.Spec.ReadinessProbe != nil { + SetDefaults_Probe(in.Spec.Template.Spec.ReadinessProbe) + } + } +} + +func SetObjectDefaults_VirtualMachineInstanceReplicaSetList(in *VirtualMachineInstanceReplicaSetList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_VirtualMachineInstanceReplicaSet(a) + } +} + +func SetObjectDefaults_VirtualMachineList(in *VirtualMachineList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_VirtualMachine(a) + } +} diff --git a/vendor/kubevirt.io/containerized-data-importer-api/LICENSE b/vendor/kubevirt.io/containerized-data-importer-api/LICENSE new file mode 100644 index 00000000..549d874d --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 The KubeVirt Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/register.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/register.go new file mode 100644 index 00000000..77f5af70 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/register.go @@ -0,0 +1,6 @@ +package core + +const ( + // GroupName to hold the string name for the cdi project + GroupName = "cdi.kubevirt.io" +) diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/doc.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/doc.go new file mode 100644 index 00000000..d6d23951 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/doc.go @@ -0,0 +1,6 @@ +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true + +// Package v1beta1 is the v1beta1 version of the API. +// +groupName=cdi.kubevirt.io +package v1beta1 diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/register.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/register.go new file mode 100644 index 00000000..3b7fd892 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/register.go @@ -0,0 +1,54 @@ +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "kubevirt.io/containerized-data-importer-api/pkg/apis/core" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: core.GroupName, Version: "v1beta1"} + +//CDIGroupVersionKind group version kind +var CDIGroupVersionKind = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: "CDI"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder tbd + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme tbd + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &DataVolume{}, + &DataVolumeList{}, + &CDIConfig{}, + &CDIConfigList{}, + &CDI{}, + &CDIList{}, + &StorageProfile{}, + &StorageProfileList{}, + &DataSource{}, + &DataSourceList{}, + &DataImportCron{}, + &DataImportCronList{}, + &ObjectTransfer{}, + &ObjectTransferList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go new file mode 100644 index 00000000..2edd93e5 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go @@ -0,0 +1,801 @@ +/* +Copyright 2018 The CDI Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + sdkapi "kubevirt.io/controller-lifecycle-operator-sdk/api" +) + +// DataVolume is an abstraction on top of PersistentVolumeClaims to allow easy population of those PersistentVolumeClaims with relation to VirtualMachines +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=dv;dvs,categories=all +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="The phase the data volume is in" +// +kubebuilder:printcolumn:name="Progress",type="string",JSONPath=".status.progress",description="Transfer progress in percentage if known, N/A otherwise" +// +kubebuilder:printcolumn:name="Restarts",type="integer",JSONPath=".status.restartCount",description="The number of times the transfer has been restarted." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +type DataVolume struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DataVolumeSpec `json:"spec"` + Status DataVolumeStatus `json:"status,omitempty"` +} + +// DataVolumeSpec defines the DataVolume type specification +type DataVolumeSpec struct { + //Source is the src of the data for the requested DataVolume + // +optional + Source *DataVolumeSource `json:"source,omitempty"` + //SourceRef is an indirect reference to the source of data for the requested DataVolume + // +optional + SourceRef *DataVolumeSourceRef `json:"sourceRef,omitempty"` + //PVC is the PVC specification + PVC *corev1.PersistentVolumeClaimSpec `json:"pvc,omitempty"` + // Storage is the requested storage specification + Storage *StorageSpec `json:"storage,omitempty"` + //PriorityClassName for Importer, Cloner and Uploader pod + PriorityClassName string `json:"priorityClassName,omitempty"` + //DataVolumeContentType options: "kubevirt", "archive" + // +kubebuilder:validation:Enum="kubevirt";"archive" + ContentType DataVolumeContentType `json:"contentType,omitempty"` + // Checkpoints is a list of DataVolumeCheckpoints, representing stages in a multistage import. + Checkpoints []DataVolumeCheckpoint `json:"checkpoints,omitempty"` + // FinalCheckpoint indicates whether the current DataVolumeCheckpoint is the final checkpoint. + FinalCheckpoint bool `json:"finalCheckpoint,omitempty"` + // Preallocation controls whether storage for DataVolumes should be allocated in advance. + Preallocation *bool `json:"preallocation,omitempty"` +} + +// StorageSpec defines the Storage type specification +type StorageSpec struct { + // AccessModes contains the desired access modes the volume should have. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + // +optional + AccessModes []corev1.PersistentVolumeAccessMode `json:"accessModes,omitempty"` + // A label query over volumes to consider for binding. + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` + // Resources represents the minimum resources the volume should have. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + // +optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + // VolumeName is the binding reference to the PersistentVolume backing this claim. + // +optional + VolumeName string `json:"volumeName,omitempty"` + // Name of the StorageClass required by the claim. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + // +optional + StorageClassName *string `json:"storageClassName,omitempty"` + // volumeMode defines what type of volume is required by the claim. + // Value of Filesystem is implied when not included in claim spec. + // +optional + VolumeMode *corev1.PersistentVolumeMode `json:"volumeMode,omitempty"` + // This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. + // +optional + DataSource *corev1.TypedLocalObjectReference `json:"dataSource,omitempty"` +} + +// DataVolumeCheckpoint defines a stage in a warm migration. +type DataVolumeCheckpoint struct { + // Previous is the identifier of the snapshot from the previous checkpoint. + Previous string `json:"previous"` + // Current is the identifier of the snapshot created for this checkpoint. + Current string `json:"current"` +} + +// DataVolumeContentType represents the types of the imported data +type DataVolumeContentType string + +const ( + // DataVolumeKubeVirt is the content-type of the imported file, defaults to kubevirt + DataVolumeKubeVirt DataVolumeContentType = "kubevirt" + // DataVolumeArchive is the content-type to specify if there is a need to extract the imported archive + DataVolumeArchive DataVolumeContentType = "archive" +) + +// DataVolumeSource represents the source for our Data Volume, this can be HTTP, Imageio, S3, Registry or an existing PVC +type DataVolumeSource struct { + HTTP *DataVolumeSourceHTTP `json:"http,omitempty"` + S3 *DataVolumeSourceS3 `json:"s3,omitempty"` + Registry *DataVolumeSourceRegistry `json:"registry,omitempty"` + PVC *DataVolumeSourcePVC `json:"pvc,omitempty"` + Upload *DataVolumeSourceUpload `json:"upload,omitempty"` + Blank *DataVolumeBlankImage `json:"blank,omitempty"` + Imageio *DataVolumeSourceImageIO `json:"imageio,omitempty"` + VDDK *DataVolumeSourceVDDK `json:"vddk,omitempty"` +} + +// DataVolumeSourcePVC provides the parameters to create a Data Volume from an existing PVC +type DataVolumeSourcePVC struct { + // The namespace of the source PVC + Namespace string `json:"namespace"` + // The name of the source PVC + Name string `json:"name"` +} + +// DataVolumeBlankImage provides the parameters to create a new raw blank image for the PVC +type DataVolumeBlankImage struct{} + +// DataVolumeSourceUpload provides the parameters to create a Data Volume by uploading the source +type DataVolumeSourceUpload struct { +} + +// DataVolumeSourceS3 provides the parameters to create a Data Volume from an S3 source +type DataVolumeSourceS3 struct { + //URL is the url of the S3 source + URL string `json:"url"` + //SecretRef provides the secret reference needed to access the S3 source + SecretRef string `json:"secretRef,omitempty"` + // CertConfigMap is a configmap reference, containing a Certificate Authority(CA) public key, and a base64 encoded pem certificate + // +optional + CertConfigMap string `json:"certConfigMap,omitempty"` +} + +// DataVolumeSourceRegistry provides the parameters to create a Data Volume from an registry source +type DataVolumeSourceRegistry struct { + //URL is the url of the registry source (starting with the scheme: docker, oci-archive) + // +optional + URL *string `json:"url,omitempty"` + //ImageStream is the name of image stream for import + // +optional + ImageStream *string `json:"imageStream,omitempty"` + //PullMethod can be either "pod" (default import), or "node" (node docker cache based import) + // +optional + PullMethod *RegistryPullMethod `json:"pullMethod,omitempty"` + //SecretRef provides the secret reference needed to access the Registry source + // +optional + SecretRef *string `json:"secretRef,omitempty"` + //CertConfigMap provides a reference to the Registry certs + // +optional + CertConfigMap *string `json:"certConfigMap,omitempty"` +} + +const ( + // RegistrySchemeDocker is docker scheme prefix + RegistrySchemeDocker = "docker" + // RegistrySchemeOci is oci-archive scheme prefix + RegistrySchemeOci = "oci-archive" +) + +// RegistryPullMethod represents the registry import pull method +type RegistryPullMethod string + +const ( + // RegistryPullPod is the standard import + RegistryPullPod RegistryPullMethod = "pod" + // RegistryPullNode is the node docker cache based import + RegistryPullNode RegistryPullMethod = "node" +) + +// DataVolumeSourceHTTP can be either an http or https endpoint, with an optional basic auth user name and password, and an optional configmap containing additional CAs +type DataVolumeSourceHTTP struct { + // URL is the URL of the http(s) endpoint + URL string `json:"url"` + // SecretRef A Secret reference, the secret should contain accessKeyId (user name) base64 encoded, and secretKey (password) also base64 encoded + // +optional + SecretRef string `json:"secretRef,omitempty"` + // CertConfigMap is a configmap reference, containing a Certificate Authority(CA) public key, and a base64 encoded pem certificate + // +optional + CertConfigMap string `json:"certConfigMap,omitempty"` + // ExtraHeaders is a list of strings containing extra headers to include with HTTP transfer requests + // +optional + ExtraHeaders []string `json:"extraHeaders,omitempty"` + // SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header that may include sensitive information + // +optional + SecretExtraHeaders []string `json:"secretExtraHeaders,omitempty"` +} + +// DataVolumeSourceImageIO provides the parameters to create a Data Volume from an imageio source +type DataVolumeSourceImageIO struct { + //URL is the URL of the ovirt-engine + URL string `json:"url"` + // DiskID provides id of a disk to be imported + DiskID string `json:"diskId"` + //SecretRef provides the secret reference needed to access the ovirt-engine + SecretRef string `json:"secretRef,omitempty"` + //CertConfigMap provides a reference to the CA cert + CertConfigMap string `json:"certConfigMap,omitempty"` +} + +// DataVolumeSourceVDDK provides the parameters to create a Data Volume from a Vmware source +type DataVolumeSourceVDDK struct { + // URL is the URL of the vCenter or ESXi host with the VM to migrate + URL string `json:"url,omitempty"` + // UUID is the UUID of the virtual machine that the backing file is attached to in vCenter/ESXi + UUID string `json:"uuid,omitempty"` + // BackingFile is the path to the virtual hard disk to migrate from vCenter/ESXi + BackingFile string `json:"backingFile,omitempty"` + // Thumbprint is the certificate thumbprint of the vCenter or ESXi host + Thumbprint string `json:"thumbprint,omitempty"` + // SecretRef provides a reference to a secret containing the username and password needed to access the vCenter or ESXi host + SecretRef string `json:"secretRef,omitempty"` + // InitImageURL is an optional URL to an image containing an extracted VDDK library, overrides v2v-vmware config map + InitImageURL string `json:"initImageURL,omitempty"` +} + +// DataVolumeSourceRef defines an indirect reference to the source of data for the DataVolume +type DataVolumeSourceRef struct { + // The kind of the source reference, currently only "DataSource" is supported + Kind string `json:"kind"` + // The namespace of the source reference, defaults to the DataVolume namespace + // +optional + Namespace *string `json:"namespace,omitempty"` + // The name of the source reference + Name string `json:"name"` +} + +const ( + // DataVolumeDataSource is DataSource source reference for DataVolume + DataVolumeDataSource = "DataSource" +) + +// DataVolumeStatus contains the current status of the DataVolume +type DataVolumeStatus struct { + // ClaimName is the name of the underlying PVC used by the DataVolume. + ClaimName string `json:"claimName,omitempty"` + //Phase is the current phase of the data volume + Phase DataVolumePhase `json:"phase,omitempty"` + Progress DataVolumeProgress `json:"progress,omitempty"` + // RestartCount is the number of times the pod populating the DataVolume has restarted + RestartCount int32 `json:"restartCount,omitempty"` + Conditions []DataVolumeCondition `json:"conditions,omitempty" optional:"true"` +} + +//DataVolumeList provides the needed parameters to do request a list of Data Volumes from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type DataVolumeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of DataVolumes + Items []DataVolume `json:"items"` +} + +// DataVolumeCondition represents the state of a data volume condition. +type DataVolumeCondition struct { + Type DataVolumeConditionType `json:"type" description:"type of condition ie. Ready|Bound|Running."` + Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime,omitempty"` + Reason string `json:"reason,omitempty" description:"reason for the condition's last transition"` + Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` +} + +// DataVolumePhase is the current phase of the DataVolume +type DataVolumePhase string + +// DataVolumeProgress is the current progress of the DataVolume transfer operation. Value between 0 and 100 inclusive, N/A if not available +type DataVolumeProgress string + +// DataVolumeConditionType is the string representation of known condition types +type DataVolumeConditionType string + +const ( + // PhaseUnset represents a data volume with no current phase + PhaseUnset DataVolumePhase = "" + + // Pending represents a data volume with a current phase of Pending + Pending DataVolumePhase = "Pending" + // PVCBound represents a data volume with a current phase of PVCBound + PVCBound DataVolumePhase = "PVCBound" + + // ImportScheduled represents a data volume with a current phase of ImportScheduled + ImportScheduled DataVolumePhase = "ImportScheduled" + + // ImportInProgress represents a data volume with a current phase of ImportInProgress + ImportInProgress DataVolumePhase = "ImportInProgress" + + // CloneScheduled represents a data volume with a current phase of CloneScheduled + CloneScheduled DataVolumePhase = "CloneScheduled" + + // CloneInProgress represents a data volume with a current phase of CloneInProgress + CloneInProgress DataVolumePhase = "CloneInProgress" + + // SnapshotForSmartCloneInProgress represents a data volume with a current phase of SnapshotForSmartCloneInProgress + SnapshotForSmartCloneInProgress DataVolumePhase = "SnapshotForSmartCloneInProgress" + + // SmartClonePVCInProgress represents a data volume with a current phase of SmartClonePVCInProgress + SmartClonePVCInProgress DataVolumePhase = "SmartClonePVCInProgress" + + // CSICloneInProgress represents a data volume with a current phase of CSICloneInProgress + CSICloneInProgress DataVolumePhase = "CSICloneInProgress" + + // ExpansionInProgress is the state when a PVC is expanded + ExpansionInProgress DataVolumePhase = "ExpansionInProgress" + + // NamespaceTransferInProgress is the state when a PVC is transferred + NamespaceTransferInProgress DataVolumePhase = "NamespaceTransferInProgress" + + // UploadScheduled represents a data volume with a current phase of UploadScheduled + UploadScheduled DataVolumePhase = "UploadScheduled" + + // UploadReady represents a data volume with a current phase of UploadReady + UploadReady DataVolumePhase = "UploadReady" + + // WaitForFirstConsumer represents a data volume with a current phase of WaitForFirstConsumer + WaitForFirstConsumer DataVolumePhase = "WaitForFirstConsumer" + + // Succeeded represents a DataVolumePhase of Succeeded + Succeeded DataVolumePhase = "Succeeded" + // Failed represents a DataVolumePhase of Failed + Failed DataVolumePhase = "Failed" + // Unknown represents a DataVolumePhase of Unknown + Unknown DataVolumePhase = "Unknown" + // Paused represents a DataVolumePhase of Paused + Paused DataVolumePhase = "Paused" + + // DataVolumeReady is the condition that indicates if the data volume is ready to be consumed. + DataVolumeReady DataVolumeConditionType = "Ready" + // DataVolumeBound is the condition that indicates if the underlying PVC is bound or not. + DataVolumeBound DataVolumeConditionType = "Bound" + // DataVolumeRunning is the condition that indicates if the import/upload/clone container is running. + DataVolumeRunning DataVolumeConditionType = "Running" +) + +// DataVolumeCloneSourceSubresource is the subresource checked for permission to clone +const DataVolumeCloneSourceSubresource = "source" + +// this has to be here otherwise informer-gen doesn't recognize it +// see https://github.com/kubernetes/code-generator/issues/59 +// +genclient:nonNamespaced + +//StorageProfile provides a CDI specific recommendation for storage parameters +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:scope=Cluster +type StorageProfile struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec StorageProfileSpec `json:"spec"` + Status StorageProfileStatus `json:"status,omitempty"` +} + +//StorageProfileSpec defines specification for StorageProfile +type StorageProfileSpec struct { + // CloneStrategy defines the preferred method for performing a CDI clone + CloneStrategy *CDICloneStrategy `json:"cloneStrategy,omitempty"` + // ClaimPropertySets is a provided set of properties applicable to PVC + ClaimPropertySets []ClaimPropertySet `json:"claimPropertySets,omitempty"` +} + +//StorageProfileStatus provides the most recently observed status of the StorageProfile +type StorageProfileStatus struct { + // The StorageClass name for which capabilities are defined + StorageClass *string `json:"storageClass,omitempty"` + // The Storage class provisioner plugin name + Provisioner *string `json:"provisioner,omitempty"` + // CloneStrategy defines the preferred method for performing a CDI clone + CloneStrategy *CDICloneStrategy `json:"cloneStrategy,omitempty"` + // ClaimPropertySets computed from the spec and detected in the system + ClaimPropertySets []ClaimPropertySet `json:"claimPropertySets,omitempty"` +} + +// ClaimPropertySet is a set of properties applicable to PVC +type ClaimPropertySet struct { + // AccessModes contains the desired access modes the volume should have. + // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + // +optional + AccessModes []corev1.PersistentVolumeAccessMode `json:"accessModes,omitempty" protobuf:"bytes,1,rep,name=accessModes,casttype=PersistentVolumeAccessMode"` + // VolumeMode defines what type of volume is required by the claim. + // Value of Filesystem is implied when not included in claim spec. + // +optional + VolumeMode *corev1.PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"` +} + +//StorageProfileList provides the needed parameters to request a list of StorageProfile from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type StorageProfileList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of StorageProfile + Items []StorageProfile `json:"items"` +} + +// DataSource references an import/clone source for a DataVolume +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=das,categories=all +type DataSource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DataSourceSpec `json:"spec"` + Status DataSourceStatus `json:"status,omitempty"` +} + +// DataSourceSpec defines specification for DataSource +type DataSourceSpec struct { + // Source is the source of the data referenced by the DataSource + Source DataSourceSource `json:"source"` +} + +// DataSourceSource represents the source for our DataSource +type DataSourceSource struct { + // +optional + PVC *DataVolumeSourcePVC `json:"pvc,omitempty"` +} + +// DataSourceStatus provides the most recently observed status of the DataSource +type DataSourceStatus struct { + Conditions []DataSourceCondition `json:"conditions,omitempty" optional:"true"` +} + +// DataSourceCondition represents the state of a data source condition +type DataSourceCondition struct { + Type DataSourceConditionType `json:"type" description:"type of condition ie. Ready"` + ConditionState `json:",inline"` +} + +// DataSourceConditionType is the string representation of known condition types +type DataSourceConditionType string + +const ( + // DataSourceReady is the condition that indicates if the data source is ready to be consumed + DataSourceReady DataSourceConditionType = "Ready" +) + +// ConditionState represents the state of a condition +type ConditionState struct { + Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime,omitempty"` + Reason string `json:"reason,omitempty" description:"reason for the condition's last transition"` + Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` +} + +// DataSourceList provides the needed parameters to do request a list of Data Sources from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type DataSourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of DataSources + Items []DataSource `json:"items"` +} + +// DataImportCron defines a cron job for recurring polling/importing disk images as PVCs into a golden image namespace +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=dic;dics,categories=all +type DataImportCron struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DataImportCronSpec `json:"spec"` + Status DataImportCronStatus `json:"status,omitempty"` +} + +// DataImportCronSpec defines specification for DataImportCron +type DataImportCronSpec struct { + // Template specifies template for the DVs to be created + Template DataVolume `json:"template"` + // Schedule specifies in cron format when and how often to look for new imports + Schedule string `json:"schedule"` + // GarbageCollect specifies whether old PVCs should be cleaned up after a new PVC is imported. + // Options are currently "Outdated" and "Never", defaults to "Outdated". + // +optional + GarbageCollect *DataImportCronGarbageCollect `json:"garbageCollect,omitempty"` + // Number of import PVCs to keep when garbage collecting. Default is 3. + // +optional + ImportsToKeep *int32 `json:"importsToKeep,omitempty"` + // ManagedDataSource specifies the name of the corresponding DataSource this cron will manage. + // DataSource has to be in the same namespace. + ManagedDataSource string `json:"managedDataSource"` + // RetentionPolicy specifies whether the created DataVolumes and DataSources are retained when their DataImportCron is deleted. Default is RatainAll. + // +optional + RetentionPolicy *DataImportCronRetentionPolicy `json:"retentionPolicy,omitempty"` +} + +// DataImportCronGarbageCollect represents the DataImportCron garbage collection mode +type DataImportCronGarbageCollect string + +const ( + // DataImportCronGarbageCollectNever specifies that garbage collection is disabled + DataImportCronGarbageCollectNever DataImportCronGarbageCollect = "Never" + // DataImportCronGarbageCollectOutdated specifies that old PVCs should be cleaned up after a new PVC is imported + DataImportCronGarbageCollectOutdated DataImportCronGarbageCollect = "Outdated" +) + +// DataImportCronRetentionPolicy represents the DataImportCron retention policy +type DataImportCronRetentionPolicy string + +const ( + // DataImportCronRetainNone specifies that the created DataVolumes and DataSources are deleted when their DataImportCron is deleted + DataImportCronRetainNone DataImportCronRetentionPolicy = "None" + // DataImportCronRetainAll specifies that the created DataVolumes and DataSources are retained when their DataImportCron is deleted + DataImportCronRetainAll DataImportCronRetentionPolicy = "All" +) + +// DataImportCronStatus provides the most recently observed status of the DataImportCron +type DataImportCronStatus struct { + // CurrentImports are the imports in progress. Currently only a single import is supported. + CurrentImports []ImportStatus `json:"currentImports,omitempty"` + // LastImportedPVC is the last imported PVC + LastImportedPVC *DataVolumeSourcePVC `json:"lastImportedPVC,omitempty"` + // LastExecutionTimestamp is the time of the last polling + LastExecutionTimestamp *metav1.Time `json:"lastExecutionTimestamp,omitempty"` + // LastImportTimestamp is the time of the last import + LastImportTimestamp *metav1.Time `json:"lastImportTimestamp,omitempty"` + Conditions []DataImportCronCondition `json:"conditions,omitempty" optional:"true"` +} + +// ImportStatus of a currently in progress import +type ImportStatus struct { + // DataVolumeName is the currently in progress import DataVolume + DataVolumeName string `json:"DataVolumeName"` + // Digest of the currently imported image + Digest string `json:"Digest"` +} + +// DataImportCronCondition represents the state of a data import cron condition +type DataImportCronCondition struct { + Type DataImportCronConditionType `json:"type" description:"type of condition ie. Progressing, UpToDate"` + ConditionState `json:",inline"` +} + +// DataImportCronConditionType is the string representation of known condition types +type DataImportCronConditionType string + +const ( + // DataImportCronProgressing is the condition that indicates import is progressing + DataImportCronProgressing DataImportCronConditionType = "Progressing" + + // DataImportCronUpToDate is the condition that indicates latest import is up to date + DataImportCronUpToDate DataImportCronConditionType = "UpToDate" +) + +// DataImportCronList provides the needed parameters to do request a list of DataImportCrons from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type DataImportCronList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of DataImportCrons + Items []DataImportCron `json:"items"` +} + +// this has to be here otherwise informer-gen doesn't recognize it +// see https://github.com/kubernetes/code-generator/issues/59 +// +genclient:nonNamespaced + +// CDI is the CDI Operator CRD +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=cdi;cdis,scope=Cluster +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase" +type CDI struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CDISpec `json:"spec"` + // +optional + Status CDIStatus `json:"status"` +} + +// CertConfig contains the tunables for TLS certificates +type CertConfig struct { + // The requested 'duration' (i.e. lifetime) of the Certificate. + Duration *metav1.Duration `json:"duration,omitempty"` + + // The amount of time before the currently issued certificate's `notAfter` + // time that we will begin to attempt to renew the certificate. + RenewBefore *metav1.Duration `json:"renewBefore,omitempty"` +} + +// CDICertConfig has the CertConfigs for CDI +type CDICertConfig struct { + // CA configuration + // CA certs are kept in the CA bundle as long as they are valid + CA *CertConfig `json:"ca,omitempty"` + + // Server configuration + // Certs are rotated and discarded + Server *CertConfig `json:"server,omitempty"` +} + +// CDISpec defines our specification for the CDI installation +type CDISpec struct { + // +kubebuilder:validation:Enum=Always;IfNotPresent;Never + // PullPolicy describes a policy for if/when to pull a container image + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty" valid:"required"` + // +kubebuilder:validation:Enum=RemoveWorkloads;BlockUninstallIfWorkloadsExist + // CDIUninstallStrategy defines the state to leave CDI on uninstall + UninstallStrategy *CDIUninstallStrategy `json:"uninstallStrategy,omitempty"` + // Rules on which nodes CDI infrastructure pods will be scheduled + Infra sdkapi.NodePlacement `json:"infra,omitempty"` + // Restrict on which nodes CDI workload pods will be scheduled + Workloads sdkapi.NodePlacement `json:"workload,omitempty"` + // Clone strategy override: should we use a host-assisted copy even if snapshots are available? + // +kubebuilder:validation:Enum="copy";"snapshot" + CloneStrategyOverride *CDICloneStrategy `json:"cloneStrategyOverride,omitempty"` + // CDIConfig at CDI level + Config *CDIConfigSpec `json:"config,omitempty"` + // certificate configuration + CertConfig *CDICertConfig `json:"certConfig,omitempty"` + // PriorityClass of the CDI control plane + PriorityClass *CDIPriorityClass `json:"priorityClass,omitempty"` +} + +// CDIPriorityClass defines the priority class of the CDI control plane. +type CDIPriorityClass string + +// CDICloneStrategy defines the preferred method for performing a CDI clone (override snapshot?) +type CDICloneStrategy string + +const ( + // CloneStrategyHostAssisted specifies slower, host-assisted copy + CloneStrategyHostAssisted = "copy" + + // CloneStrategySnapshot specifies snapshot-based copying + CloneStrategySnapshot = "snapshot" + + // CloneStrategyCsiClone specifies csi volume clone based cloning + CloneStrategyCsiClone = "csi-clone" +) + +// CDIUninstallStrategy defines the state to leave CDI on uninstall +type CDIUninstallStrategy string + +const ( + // CDIUninstallStrategyRemoveWorkloads specifies clean uninstall + CDIUninstallStrategyRemoveWorkloads CDIUninstallStrategy = "RemoveWorkloads" + + // CDIUninstallStrategyBlockUninstallIfWorkloadsExist "leaves stuff around" + CDIUninstallStrategyBlockUninstallIfWorkloadsExist CDIUninstallStrategy = "BlockUninstallIfWorkloadsExist" +) + +// CDIPhase is the current phase of the CDI deployment +type CDIPhase string + +// CDIStatus defines the status of the installation +type CDIStatus struct { + sdkapi.Status `json:",inline"` +} + +//CDIList provides the needed parameters to do request a list of CDIs from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type CDIList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of CDIs + Items []CDI `json:"items"` +} + +// this has to be here otherwise informer-gen doesn't recognize it +// see https://github.com/kubernetes/code-generator/issues/59 +// +genclient:nonNamespaced + +// CDIConfig provides a user configuration for CDI +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:scope=Cluster +type CDIConfig struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CDIConfigSpec `json:"spec"` + Status CDIConfigStatus `json:"status,omitempty"` +} + +//Percent is a string that can only be a value between [0,1) +// (Note: we actually rely on reconcile to reject invalid values) +// +kubebuilder:validation:Pattern=`^(0(?:\.\d{1,3})?|1)$` +type Percent string + +//FilesystemOverhead defines the reserved size for PVCs with VolumeMode: Filesystem +type FilesystemOverhead struct { + // Global is how much space of a Filesystem volume should be reserved for overhead. This value is used unless overridden by a more specific value (per storageClass) + Global Percent `json:"global,omitempty"` + // StorageClass specifies how much space of a Filesystem volume should be reserved for safety. The keys are the storageClass and the values are the overhead. This value overrides the global value + StorageClass map[string]Percent `json:"storageClass,omitempty"` +} + +//CDIConfigSpec defines specification for user configuration +type CDIConfigSpec struct { + // Override the URL used when uploading to a DataVolume + UploadProxyURLOverride *string `json:"uploadProxyURLOverride,omitempty"` + // ImportProxy contains importer pod proxy configuration. + // +optional + ImportProxy *ImportProxy `json:"importProxy,omitempty"` + // Override the storage class to used for scratch space during transfer operations. The scratch space storage class is determined in the following order: 1. value of scratchSpaceStorageClass, if that doesn't exist, use the default storage class, if there is no default storage class, use the storage class of the DataVolume, if no storage class specified, use no storage class for scratch space + ScratchSpaceStorageClass *string `json:"scratchSpaceStorageClass,omitempty"` + // ResourceRequirements describes the compute resource requirements. + PodResourceRequirements *corev1.ResourceRequirements `json:"podResourceRequirements,omitempty"` + // FeatureGates are a list of specific enabled feature gates + FeatureGates []string `json:"featureGates,omitempty"` + // FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A value is between 0 and 1, if not defined it is 0.055 (5.5% overhead) + FilesystemOverhead *FilesystemOverhead `json:"filesystemOverhead,omitempty"` + // Preallocation controls whether storage for DataVolumes should be allocated in advance. + Preallocation *bool `json:"preallocation,omitempty"` + // InsecureRegistries is a list of TLS disabled registries + InsecureRegistries []string `json:"insecureRegistries,omitempty"` +} + +//CDIConfigStatus provides the most recently observed status of the CDI Config resource +type CDIConfigStatus struct { + // The calculated upload proxy URL + UploadProxyURL *string `json:"uploadProxyURL,omitempty"` + // ImportProxy contains importer pod proxy configuration. + // +optional + ImportProxy *ImportProxy `json:"importProxy,omitempty"` + // The calculated storage class to be used for scratch space + ScratchSpaceStorageClass string `json:"scratchSpaceStorageClass,omitempty"` + // ResourceRequirements describes the compute resource requirements. + DefaultPodResourceRequirements *corev1.ResourceRequirements `json:"defaultPodResourceRequirements,omitempty"` + // FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A percentage value is between 0 and 1 + FilesystemOverhead *FilesystemOverhead `json:"filesystemOverhead,omitempty"` + // Preallocation controls whether storage for DataVolumes should be allocated in advance. + Preallocation bool `json:"preallocation,omitempty"` +} + +//CDIConfigList provides the needed parameters to do request a list of CDIConfigs from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type CDIConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of CDIConfigs + Items []CDIConfig `json:"items"` +} + +//ImportProxy provides the information on how to configure the importer pod proxy. +type ImportProxy struct { + // HTTPProxy is the URL http://:@: of the import proxy for HTTP requests. Empty means unset and will not result in the import pod env var. + // +optional + HTTPProxy *string `json:"HTTPProxy,omitempty"` + // HTTPSProxy is the URL https://:@: of the import proxy for HTTPS requests. Empty means unset and will not result in the import pod env var. + // +optional + HTTPSProxy *string `json:"HTTPSProxy,omitempty"` + // NoProxy is a comma-separated list of hostnames and/or CIDRs for which the proxy should not be used. Empty means unset and will not result in the import pod env var. + // +optional + NoProxy *string `json:"noProxy,omitempty"` + // TrustedCAProxy is the name of a ConfigMap in the cdi namespace that contains a user-provided trusted certificate authority (CA) bundle. + // The TrustedCAProxy field is consumed by the import controller that is resposible for coping it to a config map named trusted-ca-proxy-bundle-cm in the cdi namespace. + // Here is an example of the ConfigMap (in yaml): + // + // apiVersion: v1 + // kind: ConfigMap + // metadata: + // name: trusted-ca-proxy-bundle-cm + // namespace: cdi + // data: + // ca.pem: | + // -----BEGIN CERTIFICATE----- + // ... ... + // -----END CERTIFICATE----- + // +optional + TrustedCAProxy *string `json:"trustedCAProxy,omitempty"` +} diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go new file mode 100644 index 00000000..d4a61ed9 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go @@ -0,0 +1,395 @@ +// Code generated by swagger-doc. DO NOT EDIT. + +package v1beta1 + +func (DataVolume) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolume is an abstraction on top of PersistentVolumeClaims to allow easy population of those PersistentVolumeClaims with relation to VirtualMachines\n+genclient\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:object:root=true\n+kubebuilder:storageversion\n+kubebuilder:resource:shortName=dv;dvs,categories=all\n+kubebuilder:printcolumn:name=\"Phase\",type=\"string\",JSONPath=\".status.phase\",description=\"The phase the data volume is in\"\n+kubebuilder:printcolumn:name=\"Progress\",type=\"string\",JSONPath=\".status.progress\",description=\"Transfer progress in percentage if known, N/A otherwise\"\n+kubebuilder:printcolumn:name=\"Restarts\",type=\"integer\",JSONPath=\".status.restartCount\",description=\"The number of times the transfer has been restarted.\"\n+kubebuilder:printcolumn:name=\"Age\",type=\"date\",JSONPath=\".metadata.creationTimestamp\"", + } +} + +func (DataVolumeSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSpec defines the DataVolume type specification", + "source": "Source is the src of the data for the requested DataVolume\n+optional", + "sourceRef": "SourceRef is an indirect reference to the source of data for the requested DataVolume\n+optional", + "pvc": "PVC is the PVC specification", + "storage": "Storage is the requested storage specification", + "priorityClassName": "PriorityClassName for Importer, Cloner and Uploader pod", + "contentType": "DataVolumeContentType options: \"kubevirt\", \"archive\"\n+kubebuilder:validation:Enum=\"kubevirt\";\"archive\"", + "checkpoints": "Checkpoints is a list of DataVolumeCheckpoints, representing stages in a multistage import.", + "finalCheckpoint": "FinalCheckpoint indicates whether the current DataVolumeCheckpoint is the final checkpoint.", + "preallocation": "Preallocation controls whether storage for DataVolumes should be allocated in advance.", + } +} + +func (StorageSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StorageSpec defines the Storage type specification", + "accessModes": "AccessModes contains the desired access modes the volume should have.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1\n+optional", + "selector": "A label query over volumes to consider for binding.\n+optional", + "resources": "Resources represents the minimum resources the volume should have.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources\n+optional", + "volumeName": "VolumeName is the binding reference to the PersistentVolume backing this claim.\n+optional", + "storageClassName": "Name of the StorageClass required by the claim.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1\n+optional", + "volumeMode": "volumeMode defines what type of volume is required by the claim.\nValue of Filesystem is implied when not included in claim spec.\n+optional", + "dataSource": "This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source.\n+optional", + } +} + +func (DataVolumeCheckpoint) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeCheckpoint defines a stage in a warm migration.", + "previous": "Previous is the identifier of the snapshot from the previous checkpoint.", + "current": "Current is the identifier of the snapshot created for this checkpoint.", + } +} + +func (DataVolumeSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSource represents the source for our Data Volume, this can be HTTP, Imageio, S3, Registry or an existing PVC", + } +} + +func (DataVolumeSourcePVC) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourcePVC provides the parameters to create a Data Volume from an existing PVC", + "namespace": "The namespace of the source PVC", + "name": "The name of the source PVC", + } +} + +func (DataVolumeBlankImage) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeBlankImage provides the parameters to create a new raw blank image for the PVC", + } +} + +func (DataVolumeSourceUpload) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceUpload provides the parameters to create a Data Volume by uploading the source", + } +} + +func (DataVolumeSourceS3) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceS3 provides the parameters to create a Data Volume from an S3 source", + "url": "URL is the url of the S3 source", + "secretRef": "SecretRef provides the secret reference needed to access the S3 source", + "certConfigMap": "CertConfigMap is a configmap reference, containing a Certificate Authority(CA) public key, and a base64 encoded pem certificate\n+optional", + } +} + +func (DataVolumeSourceRegistry) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceRegistry provides the parameters to create a Data Volume from an registry source", + "url": "URL is the url of the registry source (starting with the scheme: docker, oci-archive)\n+optional", + "imageStream": "ImageStream is the name of image stream for import\n+optional", + "pullMethod": "PullMethod can be either \"pod\" (default import), or \"node\" (node docker cache based import)\n+optional", + "secretRef": "SecretRef provides the secret reference needed to access the Registry source\n+optional", + "certConfigMap": "CertConfigMap provides a reference to the Registry certs\n+optional", + } +} + +func (DataVolumeSourceHTTP) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceHTTP can be either an http or https endpoint, with an optional basic auth user name and password, and an optional configmap containing additional CAs", + "url": "URL is the URL of the http(s) endpoint", + "secretRef": "SecretRef A Secret reference, the secret should contain accessKeyId (user name) base64 encoded, and secretKey (password) also base64 encoded\n+optional", + "certConfigMap": "CertConfigMap is a configmap reference, containing a Certificate Authority(CA) public key, and a base64 encoded pem certificate\n+optional", + "extraHeaders": "ExtraHeaders is a list of strings containing extra headers to include with HTTP transfer requests\n+optional", + "secretExtraHeaders": "SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header that may include sensitive information\n+optional", + } +} + +func (DataVolumeSourceImageIO) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceImageIO provides the parameters to create a Data Volume from an imageio source", + "url": "URL is the URL of the ovirt-engine", + "diskId": "DiskID provides id of a disk to be imported", + "secretRef": "SecretRef provides the secret reference needed to access the ovirt-engine", + "certConfigMap": "CertConfigMap provides a reference to the CA cert", + } +} + +func (DataVolumeSourceVDDK) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceVDDK provides the parameters to create a Data Volume from a Vmware source", + "url": "URL is the URL of the vCenter or ESXi host with the VM to migrate", + "uuid": "UUID is the UUID of the virtual machine that the backing file is attached to in vCenter/ESXi", + "backingFile": "BackingFile is the path to the virtual hard disk to migrate from vCenter/ESXi", + "thumbprint": "Thumbprint is the certificate thumbprint of the vCenter or ESXi host", + "secretRef": "SecretRef provides a reference to a secret containing the username and password needed to access the vCenter or ESXi host", + "initImageURL": "InitImageURL is an optional URL to an image containing an extracted VDDK library, overrides v2v-vmware config map", + } +} + +func (DataVolumeSourceRef) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeSourceRef defines an indirect reference to the source of data for the DataVolume", + "kind": "The kind of the source reference, currently only \"DataSource\" is supported", + "namespace": "The namespace of the source reference, defaults to the DataVolume namespace\n+optional", + "name": "The name of the source reference", + } +} + +func (DataVolumeStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeStatus contains the current status of the DataVolume", + "claimName": "ClaimName is the name of the underlying PVC used by the DataVolume.", + "phase": "Phase is the current phase of the data volume", + "restartCount": "RestartCount is the number of times the pod populating the DataVolume has restarted", + } +} + +func (DataVolumeList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeList provides the needed parameters to do request a list of Data Volumes from the system\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "items": "Items provides a list of DataVolumes", + } +} + +func (DataVolumeCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataVolumeCondition represents the state of a data volume condition.", + } +} + +func (StorageProfile) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StorageProfile provides a CDI specific recommendation for storage parameters\n+genclient\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:object:root=true\n+kubebuilder:storageversion\n+kubebuilder:resource:scope=Cluster", + } +} + +func (StorageProfileSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StorageProfileSpec defines specification for StorageProfile", + "cloneStrategy": "CloneStrategy defines the preferred method for performing a CDI clone", + "claimPropertySets": "ClaimPropertySets is a provided set of properties applicable to PVC", + } +} + +func (StorageProfileStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StorageProfileStatus provides the most recently observed status of the StorageProfile", + "storageClass": "The StorageClass name for which capabilities are defined", + "provisioner": "The Storage class provisioner plugin name", + "cloneStrategy": "CloneStrategy defines the preferred method for performing a CDI clone", + "claimPropertySets": "ClaimPropertySets computed from the spec and detected in the system", + } +} + +func (ClaimPropertySet) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ClaimPropertySet is a set of properties applicable to PVC", + "accessModes": "AccessModes contains the desired access modes the volume should have.\nMore info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1\n+optional", + "volumeMode": "VolumeMode defines what type of volume is required by the claim.\nValue of Filesystem is implied when not included in claim spec.\n+optional", + } +} + +func (StorageProfileList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "StorageProfileList provides the needed parameters to request a list of StorageProfile from the system\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "items": "Items provides a list of StorageProfile", + } +} + +func (DataSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataSource references an import/clone source for a DataVolume\n+genclient\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:object:root=true\n+kubebuilder:storageversion\n+kubebuilder:resource:shortName=das,categories=all", + } +} + +func (DataSourceSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataSourceSpec defines specification for DataSource", + "source": "Source is the source of the data referenced by the DataSource", + } +} + +func (DataSourceSource) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataSourceSource represents the source for our DataSource", + "pvc": "+optional", + } +} + +func (DataSourceStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataSourceStatus provides the most recently observed status of the DataSource", + } +} + +func (DataSourceCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataSourceCondition represents the state of a data source condition", + } +} + +func (ConditionState) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ConditionState represents the state of a condition", + } +} + +func (DataSourceList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataSourceList provides the needed parameters to do request a list of Data Sources from the system\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "items": "Items provides a list of DataSources", + } +} + +func (DataImportCron) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataImportCron defines a cron job for recurring polling/importing disk images as PVCs into a golden image namespace\n+genclient\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:object:root=true\n+kubebuilder:storageversion\n+kubebuilder:resource:shortName=dic;dics,categories=all", + } +} + +func (DataImportCronSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataImportCronSpec defines specification for DataImportCron", + "template": "Template specifies template for the DVs to be created", + "schedule": "Schedule specifies in cron format when and how often to look for new imports", + "garbageCollect": "GarbageCollect specifies whether old PVCs should be cleaned up after a new PVC is imported.\nOptions are currently \"Outdated\" and \"Never\", defaults to \"Outdated\".\n+optional", + "importsToKeep": "Number of import PVCs to keep when garbage collecting. Default is 3.\n+optional", + "managedDataSource": "ManagedDataSource specifies the name of the corresponding DataSource this cron will manage.\nDataSource has to be in the same namespace.", + "retentionPolicy": "RetentionPolicy specifies whether the created DataVolumes and DataSources are retained when their DataImportCron is deleted. Default is RatainAll.\n+optional", + } +} + +func (DataImportCronStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataImportCronStatus provides the most recently observed status of the DataImportCron", + "currentImports": "CurrentImports are the imports in progress. Currently only a single import is supported.", + "lastImportedPVC": "LastImportedPVC is the last imported PVC", + "lastExecutionTimestamp": "LastExecutionTimestamp is the time of the last polling", + "lastImportTimestamp": "LastImportTimestamp is the time of the last import", + } +} + +func (ImportStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ImportStatus of a currently in progress import", + "DataVolumeName": "DataVolumeName is the currently in progress import DataVolume", + "Digest": "Digest of the currently imported image", + } +} + +func (DataImportCronCondition) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataImportCronCondition represents the state of a data import cron condition", + } +} + +func (DataImportCronList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "DataImportCronList provides the needed parameters to do request a list of DataImportCrons from the system\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "items": "Items provides a list of DataImportCrons", + } +} + +func (CDI) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDI is the CDI Operator CRD\n+genclient\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:object:root=true\n+kubebuilder:storageversion\n+kubebuilder:resource:shortName=cdi;cdis,scope=Cluster\n+kubebuilder:printcolumn:name=\"Age\",type=\"date\",JSONPath=\".metadata.creationTimestamp\"\n+kubebuilder:printcolumn:name=\"Phase\",type=\"string\",JSONPath=\".status.phase\"", + "status": "+optional", + } +} + +func (CertConfig) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CertConfig contains the tunables for TLS certificates", + "duration": "The requested 'duration' (i.e. lifetime) of the Certificate.", + "renewBefore": "The amount of time before the currently issued certificate's `notAfter`\ntime that we will begin to attempt to renew the certificate.", + } +} + +func (CDICertConfig) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDICertConfig has the CertConfigs for CDI", + "ca": "CA configuration\nCA certs are kept in the CA bundle as long as they are valid", + "server": "Server configuration\nCerts are rotated and discarded", + } +} + +func (CDISpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDISpec defines our specification for the CDI installation", + "imagePullPolicy": "+kubebuilder:validation:Enum=Always;IfNotPresent;Never\nPullPolicy describes a policy for if/when to pull a container image", + "uninstallStrategy": "+kubebuilder:validation:Enum=RemoveWorkloads;BlockUninstallIfWorkloadsExist\nCDIUninstallStrategy defines the state to leave CDI on uninstall", + "infra": "Rules on which nodes CDI infrastructure pods will be scheduled", + "workload": "Restrict on which nodes CDI workload pods will be scheduled", + "cloneStrategyOverride": "Clone strategy override: should we use a host-assisted copy even if snapshots are available?\n+kubebuilder:validation:Enum=\"copy\";\"snapshot\"", + "config": "CDIConfig at CDI level", + "certConfig": "certificate configuration", + "priorityClass": "PriorityClass of the CDI control plane", + } +} + +func (CDIStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDIStatus defines the status of the installation", + } +} + +func (CDIList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDIList provides the needed parameters to do request a list of CDIs from the system\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "items": "Items provides a list of CDIs", + } +} + +func (CDIConfig) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDIConfig provides a user configuration for CDI\n+genclient\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:object:root=true\n+kubebuilder:storageversion\n+kubebuilder:resource:scope=Cluster", + } +} + +func (FilesystemOverhead) SwaggerDoc() map[string]string { + return map[string]string{ + "": "FilesystemOverhead defines the reserved size for PVCs with VolumeMode: Filesystem", + "global": "Global is how much space of a Filesystem volume should be reserved for overhead. This value is used unless overridden by a more specific value (per storageClass)", + "storageClass": "StorageClass specifies how much space of a Filesystem volume should be reserved for safety. The keys are the storageClass and the values are the overhead. This value overrides the global value", + } +} + +func (CDIConfigSpec) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDIConfigSpec defines specification for user configuration", + "uploadProxyURLOverride": "Override the URL used when uploading to a DataVolume", + "importProxy": "ImportProxy contains importer pod proxy configuration.\n+optional", + "scratchSpaceStorageClass": "Override the storage class to used for scratch space during transfer operations. The scratch space storage class is determined in the following order: 1. value of scratchSpaceStorageClass, if that doesn't exist, use the default storage class, if there is no default storage class, use the storage class of the DataVolume, if no storage class specified, use no storage class for scratch space", + "podResourceRequirements": "ResourceRequirements describes the compute resource requirements.", + "featureGates": "FeatureGates are a list of specific enabled feature gates", + "filesystemOverhead": "FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A value is between 0 and 1, if not defined it is 0.055 (5.5% overhead)", + "preallocation": "Preallocation controls whether storage for DataVolumes should be allocated in advance.", + "insecureRegistries": "InsecureRegistries is a list of TLS disabled registries", + } +} + +func (CDIConfigStatus) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDIConfigStatus provides the most recently observed status of the CDI Config resource", + "uploadProxyURL": "The calculated upload proxy URL", + "importProxy": "ImportProxy contains importer pod proxy configuration.\n+optional", + "scratchSpaceStorageClass": "The calculated storage class to be used for scratch space", + "defaultPodResourceRequirements": "ResourceRequirements describes the compute resource requirements.", + "filesystemOverhead": "FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A percentage value is between 0 and 1", + "preallocation": "Preallocation controls whether storage for DataVolumes should be allocated in advance.", + } +} + +func (CDIConfigList) SwaggerDoc() map[string]string { + return map[string]string{ + "": "CDIConfigList provides the needed parameters to do request a list of CDIConfigs from the system\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object", + "items": "Items provides a list of CDIConfigs", + } +} + +func (ImportProxy) SwaggerDoc() map[string]string { + return map[string]string{ + "": "ImportProxy provides the information on how to configure the importer pod proxy.", + "HTTPProxy": "HTTPProxy is the URL http://:@: of the import proxy for HTTP requests. Empty means unset and will not result in the import pod env var.\n+optional", + "HTTPSProxy": "HTTPSProxy is the URL https://:@: of the import proxy for HTTPS requests. Empty means unset and will not result in the import pod env var.\n+optional", + "noProxy": "NoProxy is a comma-separated list of hostnames and/or CIDRs for which the proxy should not be used. Empty means unset and will not result in the import pod env var.\n+optional", + "trustedCAProxy": "TrustedCAProxy is the name of a ConfigMap in the cdi namespace that contains a user-provided trusted certificate authority (CA) bundle.\nThe TrustedCAProxy field is consumed by the import controller that is resposible for coping it to a config map named trusted-ca-proxy-bundle-cm in the cdi namespace.\nHere is an example of the ConfigMap (in yaml):\n\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: trusted-ca-proxy-bundle-cm\n namespace: cdi\ndata:\n ca.pem: |", + } +} diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_transfer.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_transfer.go new file mode 100644 index 00000000..d87e5ffb --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_transfer.go @@ -0,0 +1,134 @@ +/* +Copyright 2021 The CDI Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// this has to be here otherwise informer-gen doesn't recognize it +// see https://github.com/kubernetes/code-generator/issues/59 +// +genclient:nonNamespaced + +// ObjectTransfer is the cluster scoped object transfer resource +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=ot;ots,scope=Cluster +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="The phase of the ObjectTransfer" +// +kubebuilder:subresource:status +type ObjectTransfer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ObjectTransferSpec `json:"spec"` + + // +optional + Status ObjectTransferStatus `json:"status"` +} + +// TransferSource is the source of a ObjectTransfer +type TransferSource struct { + // +optional + APIVersion string `json:"apiVersion,omitempty"` + + Kind string `json:"kind"` + + Namespace string `json:"namespace"` + + Name string `json:"name"` + + RequiredAnnotations map[string]string `json:"requiredAnnotations,omitempty"` +} + +// TransferTarget is the target of an ObjectTransfer +type TransferTarget struct { + Namespace *string `json:"namespace,omitempty"` + + Name *string `json:"name,omitempty"` +} + +// ObjectTransferSpec specifies the source/target of the transfer +type ObjectTransferSpec struct { + Source TransferSource `json:"source"` + + Target TransferTarget `json:"target"` + + ParentName *string `json:"parentName,omitempty"` +} + +// ObjectTransferPhase is the phase of the ObjectTransfer +type ObjectTransferPhase string + +const ( + // ObjectTransferEmpty is the empty transfer phase + ObjectTransferEmpty ObjectTransferPhase = "" + + // ObjectTransferPending is the pending transfer phase + ObjectTransferPending ObjectTransferPhase = "Pending" + + // ObjectTransferRunning is the running transfer phase + ObjectTransferRunning ObjectTransferPhase = "Running" + + // ObjectTransferComplete is the complete transfer phase + ObjectTransferComplete ObjectTransferPhase = "Complete" + + // ObjectTransferError is the (terminal) error transfer phase + ObjectTransferError ObjectTransferPhase = "Error" +) + +// ObjectTransferConditionType is the type of ObjectTransferCondition +type ObjectTransferConditionType string + +const ( + // ObjectTransferConditionComplete is the "complete" condition + ObjectTransferConditionComplete ObjectTransferConditionType = "Complete" +) + +// ObjectTransferCondition contains condition data +type ObjectTransferCondition struct { + Type ObjectTransferConditionType `json:"type"` + Status corev1.ConditionStatus `json:"status"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// ObjectTransferStatus is the status of the ObjectTransfer +type ObjectTransferStatus struct { + // Data is a place for intermediary state. Or anything really. + Data map[string]string `json:"data,omitempty"` + + // Phase is the current phase of the transfer + Phase ObjectTransferPhase `json:"phase,omitempty"` + + Conditions []ObjectTransferCondition `json:"conditions,omitempty"` +} + +// ObjectTransferList provides the needed parameters to do request a list of ObjectTransfers from the system +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ObjectTransferList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of ObjectTransfers + Items []ObjectTransfer `json:"items"` +} diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/utils.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/utils.go new file mode 100644 index 00000000..b935d7f3 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/utils.go @@ -0,0 +1,61 @@ +/* +Copyright 2020 The CDI Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// IsPopulated indicates if the persistent volume passed in has been fully populated. It follow the following logic +// 1. If the PVC is not owned by a DataVolume, return true, we assume someone else has properly populated the image +// 2. If the PVC is owned by a DataVolume, look up the DV and check the phase, if phase succeeded return true +// 3. If the PVC is owned by a DataVolume, look up the DV and check the phase, if phase !succeeded return false +func IsPopulated(pvc *corev1.PersistentVolumeClaim, getDvFunc func(name, namespace string) (*DataVolume, error)) (bool, error) { + pvcOwner := metav1.GetControllerOf(pvc) + if pvcOwner != nil && pvcOwner.Kind == "DataVolume" { + // Find the data volume: + dv, err := getDvFunc(pvcOwner.Name, pvc.Namespace) + if err != nil { + return false, err + } + if dv.Status.Phase != Succeeded { + return false, nil + } + } + return true, nil +} + +// IsWaitForFirstConsumerBeforePopulating indicates if the persistent volume passed in is in ClaimPending state and waiting for first consumer. +// It follow the following logic +// 1. If the PVC is not owned by a DataVolume, return false, we can not assume it will be populated +// 2. If the PVC is owned by a DataVolume, look up the DV and check the phase, if phase WaitForFirstConsumer return true +// 3. If the PVC is owned by a DataVolume, look up the DV and check the phase, if phase !WaitForFirstConsumer return false +func IsWaitForFirstConsumerBeforePopulating(pvc *corev1.PersistentVolumeClaim, getDvFunc func(name, namespace string) (*DataVolume, error)) (bool, error) { + pvcOwner := metav1.GetControllerOf(pvc) + if pvcOwner != nil && pvcOwner.Kind == "DataVolume" { + // Find the data volume: + dv, err := getDvFunc(pvcOwner.Name, pvc.Namespace) + if err != nil { + return false, err + } + if dv.Status.Phase == WaitForFirstConsumer { + return true, nil + } + } + return false, nil +} diff --git a/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 00000000..1b93ba71 --- /dev/null +++ b/vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,1517 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2018 The CDI Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDI) DeepCopyInto(out *CDI) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDI. +func (in *CDI) DeepCopy() *CDI { + if in == nil { + return nil + } + out := new(CDI) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CDI) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDICertConfig) DeepCopyInto(out *CDICertConfig) { + *out = *in + if in.CA != nil { + in, out := &in.CA, &out.CA + *out = new(CertConfig) + (*in).DeepCopyInto(*out) + } + if in.Server != nil { + in, out := &in.Server, &out.Server + *out = new(CertConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDICertConfig. +func (in *CDICertConfig) DeepCopy() *CDICertConfig { + if in == nil { + return nil + } + out := new(CDICertConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDIConfig) DeepCopyInto(out *CDIConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDIConfig. +func (in *CDIConfig) DeepCopy() *CDIConfig { + if in == nil { + return nil + } + out := new(CDIConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CDIConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDIConfigList) DeepCopyInto(out *CDIConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CDIConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDIConfigList. +func (in *CDIConfigList) DeepCopy() *CDIConfigList { + if in == nil { + return nil + } + out := new(CDIConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CDIConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDIConfigSpec) DeepCopyInto(out *CDIConfigSpec) { + *out = *in + if in.UploadProxyURLOverride != nil { + in, out := &in.UploadProxyURLOverride, &out.UploadProxyURLOverride + *out = new(string) + **out = **in + } + if in.ImportProxy != nil { + in, out := &in.ImportProxy, &out.ImportProxy + *out = new(ImportProxy) + (*in).DeepCopyInto(*out) + } + if in.ScratchSpaceStorageClass != nil { + in, out := &in.ScratchSpaceStorageClass, &out.ScratchSpaceStorageClass + *out = new(string) + **out = **in + } + if in.PodResourceRequirements != nil { + in, out := &in.PodResourceRequirements, &out.PodResourceRequirements + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + if in.FeatureGates != nil { + in, out := &in.FeatureGates, &out.FeatureGates + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.FilesystemOverhead != nil { + in, out := &in.FilesystemOverhead, &out.FilesystemOverhead + *out = new(FilesystemOverhead) + (*in).DeepCopyInto(*out) + } + if in.Preallocation != nil { + in, out := &in.Preallocation, &out.Preallocation + *out = new(bool) + **out = **in + } + if in.InsecureRegistries != nil { + in, out := &in.InsecureRegistries, &out.InsecureRegistries + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDIConfigSpec. +func (in *CDIConfigSpec) DeepCopy() *CDIConfigSpec { + if in == nil { + return nil + } + out := new(CDIConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDIConfigStatus) DeepCopyInto(out *CDIConfigStatus) { + *out = *in + if in.UploadProxyURL != nil { + in, out := &in.UploadProxyURL, &out.UploadProxyURL + *out = new(string) + **out = **in + } + if in.ImportProxy != nil { + in, out := &in.ImportProxy, &out.ImportProxy + *out = new(ImportProxy) + (*in).DeepCopyInto(*out) + } + if in.DefaultPodResourceRequirements != nil { + in, out := &in.DefaultPodResourceRequirements, &out.DefaultPodResourceRequirements + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + if in.FilesystemOverhead != nil { + in, out := &in.FilesystemOverhead, &out.FilesystemOverhead + *out = new(FilesystemOverhead) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDIConfigStatus. +func (in *CDIConfigStatus) DeepCopy() *CDIConfigStatus { + if in == nil { + return nil + } + out := new(CDIConfigStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDIList) DeepCopyInto(out *CDIList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CDI, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDIList. +func (in *CDIList) DeepCopy() *CDIList { + if in == nil { + return nil + } + out := new(CDIList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CDIList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDISpec) DeepCopyInto(out *CDISpec) { + *out = *in + if in.UninstallStrategy != nil { + in, out := &in.UninstallStrategy, &out.UninstallStrategy + *out = new(CDIUninstallStrategy) + **out = **in + } + in.Infra.DeepCopyInto(&out.Infra) + in.Workloads.DeepCopyInto(&out.Workloads) + if in.CloneStrategyOverride != nil { + in, out := &in.CloneStrategyOverride, &out.CloneStrategyOverride + *out = new(CDICloneStrategy) + **out = **in + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(CDIConfigSpec) + (*in).DeepCopyInto(*out) + } + if in.CertConfig != nil { + in, out := &in.CertConfig, &out.CertConfig + *out = new(CDICertConfig) + (*in).DeepCopyInto(*out) + } + if in.PriorityClass != nil { + in, out := &in.PriorityClass, &out.PriorityClass + *out = new(CDIPriorityClass) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDISpec. +func (in *CDISpec) DeepCopy() *CDISpec { + if in == nil { + return nil + } + out := new(CDISpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CDIStatus) DeepCopyInto(out *CDIStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CDIStatus. +func (in *CDIStatus) DeepCopy() *CDIStatus { + if in == nil { + return nil + } + out := new(CDIStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertConfig) DeepCopyInto(out *CertConfig) { + *out = *in + if in.Duration != nil { + in, out := &in.Duration, &out.Duration + *out = new(metav1.Duration) + **out = **in + } + if in.RenewBefore != nil { + in, out := &in.RenewBefore, &out.RenewBefore + *out = new(metav1.Duration) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertConfig. +func (in *CertConfig) DeepCopy() *CertConfig { + if in == nil { + return nil + } + out := new(CertConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClaimPropertySet) DeepCopyInto(out *ClaimPropertySet) { + *out = *in + if in.AccessModes != nil { + in, out := &in.AccessModes, &out.AccessModes + *out = make([]v1.PersistentVolumeAccessMode, len(*in)) + copy(*out, *in) + } + if in.VolumeMode != nil { + in, out := &in.VolumeMode, &out.VolumeMode + *out = new(v1.PersistentVolumeMode) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimPropertySet. +func (in *ClaimPropertySet) DeepCopy() *ClaimPropertySet { + if in == nil { + return nil + } + out := new(ClaimPropertySet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConditionState) DeepCopyInto(out *ConditionState) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + in.LastHeartbeatTime.DeepCopyInto(&out.LastHeartbeatTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConditionState. +func (in *ConditionState) DeepCopy() *ConditionState { + if in == nil { + return nil + } + out := new(ConditionState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataImportCron) DeepCopyInto(out *DataImportCron) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataImportCron. +func (in *DataImportCron) DeepCopy() *DataImportCron { + if in == nil { + return nil + } + out := new(DataImportCron) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DataImportCron) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataImportCronCondition) DeepCopyInto(out *DataImportCronCondition) { + *out = *in + in.ConditionState.DeepCopyInto(&out.ConditionState) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataImportCronCondition. +func (in *DataImportCronCondition) DeepCopy() *DataImportCronCondition { + if in == nil { + return nil + } + out := new(DataImportCronCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataImportCronList) DeepCopyInto(out *DataImportCronList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DataImportCron, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataImportCronList. +func (in *DataImportCronList) DeepCopy() *DataImportCronList { + if in == nil { + return nil + } + out := new(DataImportCronList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DataImportCronList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataImportCronSpec) DeepCopyInto(out *DataImportCronSpec) { + *out = *in + in.Template.DeepCopyInto(&out.Template) + if in.GarbageCollect != nil { + in, out := &in.GarbageCollect, &out.GarbageCollect + *out = new(DataImportCronGarbageCollect) + **out = **in + } + if in.ImportsToKeep != nil { + in, out := &in.ImportsToKeep, &out.ImportsToKeep + *out = new(int32) + **out = **in + } + if in.RetentionPolicy != nil { + in, out := &in.RetentionPolicy, &out.RetentionPolicy + *out = new(DataImportCronRetentionPolicy) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataImportCronSpec. +func (in *DataImportCronSpec) DeepCopy() *DataImportCronSpec { + if in == nil { + return nil + } + out := new(DataImportCronSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataImportCronStatus) DeepCopyInto(out *DataImportCronStatus) { + *out = *in + if in.CurrentImports != nil { + in, out := &in.CurrentImports, &out.CurrentImports + *out = make([]ImportStatus, len(*in)) + copy(*out, *in) + } + if in.LastImportedPVC != nil { + in, out := &in.LastImportedPVC, &out.LastImportedPVC + *out = new(DataVolumeSourcePVC) + **out = **in + } + if in.LastExecutionTimestamp != nil { + in, out := &in.LastExecutionTimestamp, &out.LastExecutionTimestamp + *out = (*in).DeepCopy() + } + if in.LastImportTimestamp != nil { + in, out := &in.LastImportTimestamp, &out.LastImportTimestamp + *out = (*in).DeepCopy() + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]DataImportCronCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataImportCronStatus. +func (in *DataImportCronStatus) DeepCopy() *DataImportCronStatus { + if in == nil { + return nil + } + out := new(DataImportCronStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataSource) DeepCopyInto(out *DataSource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSource. +func (in *DataSource) DeepCopy() *DataSource { + if in == nil { + return nil + } + out := new(DataSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DataSource) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataSourceCondition) DeepCopyInto(out *DataSourceCondition) { + *out = *in + in.ConditionState.DeepCopyInto(&out.ConditionState) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceCondition. +func (in *DataSourceCondition) DeepCopy() *DataSourceCondition { + if in == nil { + return nil + } + out := new(DataSourceCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataSourceList) DeepCopyInto(out *DataSourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DataSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceList. +func (in *DataSourceList) DeepCopy() *DataSourceList { + if in == nil { + return nil + } + out := new(DataSourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DataSourceList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataSourceSource) DeepCopyInto(out *DataSourceSource) { + *out = *in + if in.PVC != nil { + in, out := &in.PVC, &out.PVC + *out = new(DataVolumeSourcePVC) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceSource. +func (in *DataSourceSource) DeepCopy() *DataSourceSource { + if in == nil { + return nil + } + out := new(DataSourceSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataSourceSpec) DeepCopyInto(out *DataSourceSpec) { + *out = *in + in.Source.DeepCopyInto(&out.Source) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceSpec. +func (in *DataSourceSpec) DeepCopy() *DataSourceSpec { + if in == nil { + return nil + } + out := new(DataSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataSourceStatus) DeepCopyInto(out *DataSourceStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]DataSourceCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceStatus. +func (in *DataSourceStatus) DeepCopy() *DataSourceStatus { + if in == nil { + return nil + } + out := new(DataSourceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolume) DeepCopyInto(out *DataVolume) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolume. +func (in *DataVolume) DeepCopy() *DataVolume { + if in == nil { + return nil + } + out := new(DataVolume) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DataVolume) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeBlankImage) DeepCopyInto(out *DataVolumeBlankImage) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeBlankImage. +func (in *DataVolumeBlankImage) DeepCopy() *DataVolumeBlankImage { + if in == nil { + return nil + } + out := new(DataVolumeBlankImage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeCheckpoint) DeepCopyInto(out *DataVolumeCheckpoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeCheckpoint. +func (in *DataVolumeCheckpoint) DeepCopy() *DataVolumeCheckpoint { + if in == nil { + return nil + } + out := new(DataVolumeCheckpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeCondition) DeepCopyInto(out *DataVolumeCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + in.LastHeartbeatTime.DeepCopyInto(&out.LastHeartbeatTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeCondition. +func (in *DataVolumeCondition) DeepCopy() *DataVolumeCondition { + if in == nil { + return nil + } + out := new(DataVolumeCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeList) DeepCopyInto(out *DataVolumeList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DataVolume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeList. +func (in *DataVolumeList) DeepCopy() *DataVolumeList { + if in == nil { + return nil + } + out := new(DataVolumeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DataVolumeList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSource) DeepCopyInto(out *DataVolumeSource) { + *out = *in + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(DataVolumeSourceHTTP) + (*in).DeepCopyInto(*out) + } + if in.S3 != nil { + in, out := &in.S3, &out.S3 + *out = new(DataVolumeSourceS3) + **out = **in + } + if in.Registry != nil { + in, out := &in.Registry, &out.Registry + *out = new(DataVolumeSourceRegistry) + (*in).DeepCopyInto(*out) + } + if in.PVC != nil { + in, out := &in.PVC, &out.PVC + *out = new(DataVolumeSourcePVC) + **out = **in + } + if in.Upload != nil { + in, out := &in.Upload, &out.Upload + *out = new(DataVolumeSourceUpload) + **out = **in + } + if in.Blank != nil { + in, out := &in.Blank, &out.Blank + *out = new(DataVolumeBlankImage) + **out = **in + } + if in.Imageio != nil { + in, out := &in.Imageio, &out.Imageio + *out = new(DataVolumeSourceImageIO) + **out = **in + } + if in.VDDK != nil { + in, out := &in.VDDK, &out.VDDK + *out = new(DataVolumeSourceVDDK) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSource. +func (in *DataVolumeSource) DeepCopy() *DataVolumeSource { + if in == nil { + return nil + } + out := new(DataVolumeSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceHTTP) DeepCopyInto(out *DataVolumeSourceHTTP) { + *out = *in + if in.ExtraHeaders != nil { + in, out := &in.ExtraHeaders, &out.ExtraHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.SecretExtraHeaders != nil { + in, out := &in.SecretExtraHeaders, &out.SecretExtraHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceHTTP. +func (in *DataVolumeSourceHTTP) DeepCopy() *DataVolumeSourceHTTP { + if in == nil { + return nil + } + out := new(DataVolumeSourceHTTP) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceImageIO) DeepCopyInto(out *DataVolumeSourceImageIO) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceImageIO. +func (in *DataVolumeSourceImageIO) DeepCopy() *DataVolumeSourceImageIO { + if in == nil { + return nil + } + out := new(DataVolumeSourceImageIO) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourcePVC) DeepCopyInto(out *DataVolumeSourcePVC) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourcePVC. +func (in *DataVolumeSourcePVC) DeepCopy() *DataVolumeSourcePVC { + if in == nil { + return nil + } + out := new(DataVolumeSourcePVC) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceRef) DeepCopyInto(out *DataVolumeSourceRef) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceRef. +func (in *DataVolumeSourceRef) DeepCopy() *DataVolumeSourceRef { + if in == nil { + return nil + } + out := new(DataVolumeSourceRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceRegistry) DeepCopyInto(out *DataVolumeSourceRegistry) { + *out = *in + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(string) + **out = **in + } + if in.ImageStream != nil { + in, out := &in.ImageStream, &out.ImageStream + *out = new(string) + **out = **in + } + if in.PullMethod != nil { + in, out := &in.PullMethod, &out.PullMethod + *out = new(RegistryPullMethod) + **out = **in + } + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(string) + **out = **in + } + if in.CertConfigMap != nil { + in, out := &in.CertConfigMap, &out.CertConfigMap + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceRegistry. +func (in *DataVolumeSourceRegistry) DeepCopy() *DataVolumeSourceRegistry { + if in == nil { + return nil + } + out := new(DataVolumeSourceRegistry) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceS3) DeepCopyInto(out *DataVolumeSourceS3) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceS3. +func (in *DataVolumeSourceS3) DeepCopy() *DataVolumeSourceS3 { + if in == nil { + return nil + } + out := new(DataVolumeSourceS3) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceUpload) DeepCopyInto(out *DataVolumeSourceUpload) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceUpload. +func (in *DataVolumeSourceUpload) DeepCopy() *DataVolumeSourceUpload { + if in == nil { + return nil + } + out := new(DataVolumeSourceUpload) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSourceVDDK) DeepCopyInto(out *DataVolumeSourceVDDK) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSourceVDDK. +func (in *DataVolumeSourceVDDK) DeepCopy() *DataVolumeSourceVDDK { + if in == nil { + return nil + } + out := new(DataVolumeSourceVDDK) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeSpec) DeepCopyInto(out *DataVolumeSpec) { + *out = *in + if in.Source != nil { + in, out := &in.Source, &out.Source + *out = new(DataVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.SourceRef != nil { + in, out := &in.SourceRef, &out.SourceRef + *out = new(DataVolumeSourceRef) + (*in).DeepCopyInto(*out) + } + if in.PVC != nil { + in, out := &in.PVC, &out.PVC + *out = new(v1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(StorageSpec) + (*in).DeepCopyInto(*out) + } + if in.Checkpoints != nil { + in, out := &in.Checkpoints, &out.Checkpoints + *out = make([]DataVolumeCheckpoint, len(*in)) + copy(*out, *in) + } + if in.Preallocation != nil { + in, out := &in.Preallocation, &out.Preallocation + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeSpec. +func (in *DataVolumeSpec) DeepCopy() *DataVolumeSpec { + if in == nil { + return nil + } + out := new(DataVolumeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataVolumeStatus) DeepCopyInto(out *DataVolumeStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]DataVolumeCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeStatus. +func (in *DataVolumeStatus) DeepCopy() *DataVolumeStatus { + if in == nil { + return nil + } + out := new(DataVolumeStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FilesystemOverhead) DeepCopyInto(out *FilesystemOverhead) { + *out = *in + if in.StorageClass != nil { + in, out := &in.StorageClass, &out.StorageClass + *out = make(map[string]Percent, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FilesystemOverhead. +func (in *FilesystemOverhead) DeepCopy() *FilesystemOverhead { + if in == nil { + return nil + } + out := new(FilesystemOverhead) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportProxy) DeepCopyInto(out *ImportProxy) { + *out = *in + if in.HTTPProxy != nil { + in, out := &in.HTTPProxy, &out.HTTPProxy + *out = new(string) + **out = **in + } + if in.HTTPSProxy != nil { + in, out := &in.HTTPSProxy, &out.HTTPSProxy + *out = new(string) + **out = **in + } + if in.NoProxy != nil { + in, out := &in.NoProxy, &out.NoProxy + *out = new(string) + **out = **in + } + if in.TrustedCAProxy != nil { + in, out := &in.TrustedCAProxy, &out.TrustedCAProxy + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportProxy. +func (in *ImportProxy) DeepCopy() *ImportProxy { + if in == nil { + return nil + } + out := new(ImportProxy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportStatus) DeepCopyInto(out *ImportStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportStatus. +func (in *ImportStatus) DeepCopy() *ImportStatus { + if in == nil { + return nil + } + out := new(ImportStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectTransfer) DeepCopyInto(out *ObjectTransfer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTransfer. +func (in *ObjectTransfer) DeepCopy() *ObjectTransfer { + if in == nil { + return nil + } + out := new(ObjectTransfer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ObjectTransfer) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectTransferCondition) DeepCopyInto(out *ObjectTransferCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + in.LastHeartbeatTime.DeepCopyInto(&out.LastHeartbeatTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTransferCondition. +func (in *ObjectTransferCondition) DeepCopy() *ObjectTransferCondition { + if in == nil { + return nil + } + out := new(ObjectTransferCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectTransferList) DeepCopyInto(out *ObjectTransferList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ObjectTransfer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTransferList. +func (in *ObjectTransferList) DeepCopy() *ObjectTransferList { + if in == nil { + return nil + } + out := new(ObjectTransferList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ObjectTransferList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectTransferSpec) DeepCopyInto(out *ObjectTransferSpec) { + *out = *in + in.Source.DeepCopyInto(&out.Source) + in.Target.DeepCopyInto(&out.Target) + if in.ParentName != nil { + in, out := &in.ParentName, &out.ParentName + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTransferSpec. +func (in *ObjectTransferSpec) DeepCopy() *ObjectTransferSpec { + if in == nil { + return nil + } + out := new(ObjectTransferSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectTransferStatus) DeepCopyInto(out *ObjectTransferStatus) { + *out = *in + if in.Data != nil { + in, out := &in.Data, &out.Data + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ObjectTransferCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTransferStatus. +func (in *ObjectTransferStatus) DeepCopy() *ObjectTransferStatus { + if in == nil { + return nil + } + out := new(ObjectTransferStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageProfile) DeepCopyInto(out *StorageProfile) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageProfile. +func (in *StorageProfile) DeepCopy() *StorageProfile { + if in == nil { + return nil + } + out := new(StorageProfile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *StorageProfile) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageProfileList) DeepCopyInto(out *StorageProfileList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]StorageProfile, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageProfileList. +func (in *StorageProfileList) DeepCopy() *StorageProfileList { + if in == nil { + return nil + } + out := new(StorageProfileList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *StorageProfileList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageProfileSpec) DeepCopyInto(out *StorageProfileSpec) { + *out = *in + if in.CloneStrategy != nil { + in, out := &in.CloneStrategy, &out.CloneStrategy + *out = new(CDICloneStrategy) + **out = **in + } + if in.ClaimPropertySets != nil { + in, out := &in.ClaimPropertySets, &out.ClaimPropertySets + *out = make([]ClaimPropertySet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageProfileSpec. +func (in *StorageProfileSpec) DeepCopy() *StorageProfileSpec { + if in == nil { + return nil + } + out := new(StorageProfileSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageProfileStatus) DeepCopyInto(out *StorageProfileStatus) { + *out = *in + if in.StorageClass != nil { + in, out := &in.StorageClass, &out.StorageClass + *out = new(string) + **out = **in + } + if in.Provisioner != nil { + in, out := &in.Provisioner, &out.Provisioner + *out = new(string) + **out = **in + } + if in.CloneStrategy != nil { + in, out := &in.CloneStrategy, &out.CloneStrategy + *out = new(CDICloneStrategy) + **out = **in + } + if in.ClaimPropertySets != nil { + in, out := &in.ClaimPropertySets, &out.ClaimPropertySets + *out = make([]ClaimPropertySet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageProfileStatus. +func (in *StorageProfileStatus) DeepCopy() *StorageProfileStatus { + if in == nil { + return nil + } + out := new(StorageProfileStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageSpec) DeepCopyInto(out *StorageSpec) { + *out = *in + if in.AccessModes != nil { + in, out := &in.AccessModes, &out.AccessModes + *out = make([]v1.PersistentVolumeAccessMode, len(*in)) + copy(*out, *in) + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + in.Resources.DeepCopyInto(&out.Resources) + if in.StorageClassName != nil { + in, out := &in.StorageClassName, &out.StorageClassName + *out = new(string) + **out = **in + } + if in.VolumeMode != nil { + in, out := &in.VolumeMode, &out.VolumeMode + *out = new(v1.PersistentVolumeMode) + **out = **in + } + if in.DataSource != nil { + in, out := &in.DataSource, &out.DataSource + *out = new(v1.TypedLocalObjectReference) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageSpec. +func (in *StorageSpec) DeepCopy() *StorageSpec { + if in == nil { + return nil + } + out := new(StorageSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TransferSource) DeepCopyInto(out *TransferSource) { + *out = *in + if in.RequiredAnnotations != nil { + in, out := &in.RequiredAnnotations, &out.RequiredAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TransferSource. +func (in *TransferSource) DeepCopy() *TransferSource { + if in == nil { + return nil + } + out := new(TransferSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TransferTarget) DeepCopyInto(out *TransferTarget) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TransferTarget. +func (in *TransferTarget) DeepCopy() *TransferTarget { + if in == nil { + return nil + } + out := new(TransferTarget) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/LICENSE b/vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/types.go b/vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/types.go new file mode 100644 index 00000000..b99715c3 --- /dev/null +++ b/vendor/kubevirt.io/controller-lifecycle-operator-sdk/api/types.go @@ -0,0 +1,130 @@ +package api + +import ( + conditions "github.com/openshift/custom-resource-status/conditions/v1" + corev1 "k8s.io/api/core/v1" +) + +// Phase is the current phase of the deployment +type Phase string + +const ( + // PhaseDeploying signals that the resources are being deployed + PhaseDeploying Phase = "Deploying" + + // PhaseDeployed signals that the resources are successfully deployed + PhaseDeployed Phase = "Deployed" + + // PhaseDeleting signals that the resources are being removed + PhaseDeleting Phase = "Deleting" + + // PhaseDeleted signals that the resources are deleted + PhaseDeleted Phase = "Deleted" + + // PhaseError signals that the deployment is in an error state + PhaseError Phase = "Error" + + // PhaseUpgrading signals that the resources are being deployed + PhaseUpgrading Phase = "Upgrading" + + // PhaseEmpty is an uninitialized phase + PhaseEmpty Phase = "" +) + +// Status represents status of a operator configuration resource; must be inlined in the operator configuration resource status +type Status struct { + Phase Phase `json:"phase,omitempty"` + // A list of current conditions of the resource + Conditions []conditions.Condition `json:"conditions,omitempty" optional:"true"` + // The version of the resource as defined by the operator + OperatorVersion string `json:"operatorVersion,omitempty" optional:"true"` + // The desired version of the resource + TargetVersion string `json:"targetVersion,omitempty" optional:"true"` + // The observed version of the resource + ObservedVersion string `json:"observedVersion,omitempty" optional:"true"` +} + +// NodePlacement describes node scheduling configuration. +// +k8s:openapi-gen=true +type NodePlacement struct { + // nodeSelector is the node selector applied to the relevant kind of pods + // It specifies a map of key-value pairs: for the pod to be eligible to run on a node, + // the node must have each of the indicated key-value pairs as labels + // (it can have additional labels as well). + // See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + // +kubebuilder:validation:Optional + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // affinity enables pod affinity/anti-affinity placement expanding the types of constraints + // that can be expressed with nodeSelector. + // affinity is going to be applied to the relevant kind of pods in parallel with nodeSelector + // See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity + // +kubebuilder:validation:Optional + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + + // tolerations is a list of tolerations applied to the relevant kind of pods + // See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info. + // These are additional tolerations other than default ones. + // +kubebuilder:validation:Optional + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` +} + +// DeepCopyInto is copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]conditions.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodePlacement) DeepCopyInto(out *NodePlacement) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(corev1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodePlacement. +func (in *NodePlacement) DeepCopy() *NodePlacement { + if in == nil { + return nil + } + out := new(NodePlacement) + in.DeepCopyInto(out) + return out +} + +// SwaggerDoc provides documentation for NodePlacement +func (NodePlacement) SwaggerDoc() map[string]string { + return map[string]string{ + "": "NodePlacement describes node scheduling configuration.", + "nodeSelector": "nodeSelector is the node selector applied to the relevant kind of pods\nIt specifies a map of key-value pairs: for the pod to be eligible to run on a node,\nthe node must have each of the indicated key-value pairs as labels\n(it can have additional labels as well).\nSee https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector\n+kubebuilder:validation:Optional\n+optional", + "affinity": "affinity enables pod affinity/anti-affinity placement expanding the types of constraints\nthat can be expressed with nodeSelector.\naffinity is going to be applied to the relevant kind of pods in parallel with nodeSelector\nSee https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity\n+kubebuilder:validation:Optional\n+optional", + "tolerations": "tolerations is a list of tolerations applied to the relevant kind of pods\nSee https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info.\nThese are additional tolerations other than default ones.\n+kubebuilder:validation:Optional\n+optional", + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 327426ed..f18b2002 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -236,6 +236,12 @@ github.com/onsi/gomega/types # github.com/openshift/api v3.9.0+incompatible ## explicit github.com/openshift/api/build/v1 +# github.com/openshift/custom-resource-status v1.1.2 +## explicit; go 1.12 +github.com/openshift/custom-resource-status/conditions/v1 +# github.com/pborman/uuid v1.2.0 +## explicit +github.com/pborman/uuid # github.com/pkg/errors v0.9.1 ## explicit github.com/pkg/errors @@ -287,10 +293,19 @@ go.uber.org/zap/internal/bufferpool go.uber.org/zap/internal/color go.uber.org/zap/internal/exit go.uber.org/zap/zapcore -# golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 +# golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d ## explicit; go 1.17 +golang.org/x/crypto/blowfish +golang.org/x/crypto/chacha20 +golang.org/x/crypto/curve25519 +golang.org/x/crypto/curve25519/internal/field +golang.org/x/crypto/ed25519 +golang.org/x/crypto/internal/poly1305 +golang.org/x/crypto/internal/subtle golang.org/x/crypto/pkcs12 golang.org/x/crypto/pkcs12/internal/rc2 +golang.org/x/crypto/ssh +golang.org/x/crypto/ssh/internal/bcrypt_pbkdf # golang.org/x/net v0.0.0-20220513224357-95641704303c ## explicit; go 1.17 golang.org/x/net/context @@ -313,6 +328,7 @@ golang.org/x/oauth2/jws golang.org/x/oauth2/jwt # golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a ## explicit; go 1.17 +golang.org/x/sys/cpu golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 golang.org/x/sys/unix @@ -676,6 +692,17 @@ k8s.io/utils/net k8s.io/utils/pointer k8s.io/utils/strings/slices k8s.io/utils/trace +# kubevirt.io/api v0.54.0 +## explicit; go 1.17 +kubevirt.io/api/core +kubevirt.io/api/core/v1 +# kubevirt.io/containerized-data-importer-api v1.47.0 +## explicit; go 1.17 +kubevirt.io/containerized-data-importer-api/pkg/apis/core +kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1 +# kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 +## explicit; go 1.17 +kubevirt.io/controller-lifecycle-operator-sdk/api # sigs.k8s.io/controller-runtime v0.12.3 ## explicit; go 1.17 sigs.k8s.io/controller-runtime