From ed9244efee0ac5079ec846fa219e0533f205be88 Mon Sep 17 00:00:00 2001 From: Daniil Antoshin Date: Fri, 15 Nov 2024 15:47:14 +0200 Subject: [PATCH] feat(cvi/vi): generate crd (#507) Generate ClusterVirtualImage and VirtualImage CRD by controller-gen --------- Signed-off-by: Daniil Antoshin --- api/Taskfile.dist.yaml | 2 +- api/core/v1alpha2/cluster_virtual_image.go | 99 ++- api/core/v1alpha2/data_source.go | 57 +- api/core/v1alpha2/image_status.go | 56 +- api/core/v1alpha2/virtual_disk.go | 20 +- api/core/v1alpha2/virtual_image.go | 102 ++- api/core/v1alpha2/zz_generated.deepcopy.go | 213 +++++-- .../generated/openapi/zz_generated.openapi.go | 587 ++++++++++-------- api/scripts/update-codegen.sh | 4 +- crds/clustervirtualimages.yaml | 535 ++++++++-------- crds/virtualimages.yaml | 561 +++++++++-------- .../pkg/common/datasource/ca_bundle.go | 92 ++- .../common/datasource/image_pull_secret.go | 4 +- .../pkg/controller/cvi/internal/life_cycle.go | 4 +- .../cvi/internal/source/registry.go | 10 +- .../pkg/controller/importer/settings.go | 3 +- .../pkg/controller/supplements/ensure.go | 6 +- .../pkg/controller/vd/internal/source/http.go | 2 +- .../controller/vd/internal/source/registry.go | 13 +- .../controller/vd/internal/source/upload.go | 2 +- .../pkg/controller/vi/internal/life_cycle.go | 8 +- .../pkg/controller/vi/internal/source/http.go | 4 +- .../vi/internal/source/object_ref.go | 2 +- .../vi/internal/source/object_ref_vd.go | 2 +- .../internal/source/object_ref_vi_on_pvc.go | 2 +- .../controller/vi/internal/source/registry.go | 16 +- .../controller/vi/internal/source/upload.go | 4 +- .../vm/internal/block_devices_test.go | 8 +- 28 files changed, 1428 insertions(+), 990 deletions(-) diff --git a/api/Taskfile.dist.yaml b/api/Taskfile.dist.yaml index 8781f1567..685431549 100644 --- a/api/Taskfile.dist.yaml +++ b/api/Taskfile.dist.yaml @@ -7,7 +7,7 @@ env: sh: echo $(go env GOMODCACHE)/$(go list -f '{{`{{.Path}}@{{.Version}}`}}' -m k8s.io/code-generator) vars: - CONTROLLER_GEN_VERSION: 0.14.0 + CONTROLLER_GEN_VERSION: 0.16.4 tasks: generate: diff --git a/api/core/v1alpha2/cluster_virtual_image.go b/api/core/v1alpha2/cluster_virtual_image.go index d724f96d2..bb4c0836c 100644 --- a/api/core/v1alpha2/cluster_virtual_image.go +++ b/api/core/v1alpha2/cluster_virtual_image.go @@ -18,6 +18,7 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" ) const ( @@ -25,10 +26,26 @@ const ( ClusterVirtualImageResource = "clustervirtualimages" ) -// +genclient:nonNamespaced - -// ClusterVirtualImage is a cluster wide available image for virtual machines. +// Describes a virtual disk image that can be used as a data source for new `VirtualDisks` or an installation image (iso) to be mounted in `Virtuals` directly. This resource type is available for all namespaces in the cluster. +// +// > This resource cannot be modified once it has been created. +// +// A container image is created under the hood of this resource, which is stored in a dedicated deckhouse virtualization container registry (DVCR). +// +// +kubebuilder:object:root=true +// +kubebuilder:metadata:labels={heritage=deckhouse,module=virtualization,backup.deckhouse.io/cluster-config=true} +// +kubebuilder:resource:categories={virtualization},scope=Cluster,shortName={cvi,cvis},singular=clustervirtualimage +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="CDROM",type=boolean,JSONPath=`.status.cdrom` +// +kubebuilder:printcolumn:name="Progress",type=string,JSONPath=`.status.progress` +// +kubebuilder:printcolumn:name="StoredSize",type=string,JSONPath=`.status.size.stored`,priority=1 +// +kubebuilder:printcolumn:name="UnpackedSize",type=string,JSONPath=`.status.size.unpacked`,priority=1 +// +kubebuilder:printcolumn:name="Registry URL",type=string,JSONPath=`.status.target.registryURL`,priority=1 +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:validation:XValidation:rule="self.metadata.name.size() <= 128",message="The name must be no longer than 128 characters." // +genclient +// +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ClusterVirtualImage struct { metav1.TypeMeta `json:",inline"` @@ -55,19 +72,43 @@ type ClusterVirtualImageSpec struct { DataSource ClusterVirtualImageDataSource `json:"dataSource"` } +// An origin of the image. +// +kubebuilder:validation:XValidation:rule="self.type == 'HTTP' ? has(self.http) && !has(self.containerImage) && !has(self.objectRef) : true",message="HTTP requires http and cannot have ContainerImage or ObjectRef" +// +kubebuilder:validation:XValidation:rule="self.type == 'ContainerImage' ? has(self.containerImage) && !has(self.http) && !has(self.objectRef) : true",message="ContainerImage requires containerImage and cannot have HTTP or ObjectRef" +// +kubebuilder:validation:XValidation:rule="self.type == 'ObjectRef' ? has(self.objectRef) && !has(self.http) && !has(self.containerImage) : true",message="ObjectRef requires objectRef and cannot have HTTP or ContainerImage" type ClusterVirtualImageDataSource struct { - Type DataSourceType `json:"type,omitempty"` - HTTP *DataSourceHTTP `json:"http,omitempty"` - ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` - ObjectRef *ClusterVirtualImageObjectRef `json:"objectRef,omitempty"` + Type DataSourceType `json:"type"` + HTTP *DataSourceHTTP `json:"http,omitempty"` + ContainerImage *ClusterVirtualImageContainerImage `json:"containerImage,omitempty"` + ObjectRef *ClusterVirtualImageObjectRef `json:"objectRef,omitempty"` } +// Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed. +type ClusterVirtualImageContainerImage struct { + // The container registry address of an image. + // +kubebuilder:example:="registry.example.com/images/slackware:15" + // +kubebuilder:validation:Pattern:=`^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$` + Image string `json:"image"` + ImagePullSecret ImagePullSecret `json:"imagePullSecret,omitempty"` + // The CA chain in base64 format to verify the container registry. + // +kubebuilder:example:="YWFhCg==" + CABundle []byte `json:"caBundle,omitempty"` +} + +// Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk` to create an image. +// +// +kubebuilder:validation:XValidation:rule="self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' ? has(self.__namespace__) && size(self.__namespace__) > 0 : true",message="The namespace is required for VirtualDisk and VirtualImage" +// +kubebuilder:validation:XValidation:rule="self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' ? has(self.__namespace__) && size(self.__namespace__) < 64 : true",message="The namespace must be no longer than 63 characters." type ClusterVirtualImageObjectRef struct { - Kind ClusterVirtualImageObjectRefKind `json:"kind,omitempty"` - Name string `json:"name,omitempty"` - Namespace string `json:"namespace,omitempty"` + Kind ClusterVirtualImageObjectRefKind `json:"kind"` + // A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. + Name string `json:"name"` + // A namespace where `VirtualImage` or `VirtualDisk` is located. + Namespace string `json:"namespace,omitempty"` } +// A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. +// +kubebuilder:validation:Enum:={ClusterVirtualImage,VirtualImage,VirtualDisk} type ClusterVirtualImageObjectRefKind string const ( @@ -77,7 +118,39 @@ const ( ) type ClusterVirtualImageStatus struct { - ImageStatus `json:",inline"` - Conditions []metav1.Condition `json:"conditions,omitempty"` - ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // Image download speed from an external source. Appears only during the `Provisioning` phase. + DownloadSpeed *StatusSpeed `json:"downloadSpeed,omitempty"` + // Discovered sizes of the image. + Size ImageStatusSize `json:"size,omitempty"` + // Discovered format of the image. + Format string `json:"format,omitempty"` + // Whether the image is a format that is supposed to be mounted as a cdrom, such as iso and so on. + CDROM bool `json:"cdrom,omitempty"` + // Current status of `ClusterVirtualImage` resource: + // * Pending - The resource has been created and is on a waiting queue. + // * Provisioning - The process of resource creation (copying/downloading/building the image) is in progress. + // * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. + // * Ready - The resource is created and ready to use. + // * Failed - There was a problem when creating a resource. + // * Terminating - The process of resource deletion is in progress. + // +kubebuilder:validation:Enum:={Pending,Provisioning,WaitForUserUpload,Ready,Failed,Terminating} + Phase ImagePhase `json:"phase,omitempty"` + // Progress of copying an image from source to DVCR. Appears only during the `Provisioning' phase. + Progress string `json:"progress,omitempty"` + // The UID of the source (`VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`) used when creating the cluster virtual image. + SourceUID *types.UID `json:"sourceUID,omitempty"` + // The latest available observations of an object's current state. + Conditions []metav1.Condition `json:"conditions,omitempty"` + // The generation last processed by the controller. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // Deprecated. Use imageUploadURLs instead. + UploadCommand string `json:"uploadCommand,omitempty"` + ImageUploadURLs *ImageUploadURLs `json:"imageUploadURLs,omitempty"` + Target ClusterVirtualImageStatusTarget `json:"target,omitempty"` +} + +type ClusterVirtualImageStatusTarget struct { + // Created image in DVCR. + // +kubebuilder:example:="dvcr..svc/cvi/:latest" + RegistryURL string `json:"registryURL,omitempty"` } diff --git a/api/core/v1alpha2/data_source.go b/api/core/v1alpha2/data_source.go index 027d1c3dd..3d4a43d81 100644 --- a/api/core/v1alpha2/data_source.go +++ b/api/core/v1alpha2/data_source.go @@ -16,28 +16,65 @@ limitations under the License. package v1alpha2 +// Fill the image with data from some external url. Supported schemas are: +// +// * http +// * https +// +// For https schema there is an option to skip TLS verification. type DataSourceHTTP struct { - URL string `json:"url"` - CABundle []byte `json:"caBundle"` + // A checksum of the file, provided by the url, to verify if it was downloaded correctly or wasn't changed. The file should match all specified checksums. Checksum *Checksum `json:"checksum,omitempty"` + // The http url with an image. The following formats are supported: + // * qcow2 + // * vmdk + // * vdi + // * iso + // * raw + // these formats can also be compressed with the following formats: + // * gz + // * xz + // +kubebuilder:example:="https://mirror.example.com/images/slackware-15.qcow.gz" + // +kubebuilder:validation:Pattern=`^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$` + URL string `json:"url"` + // The CA chain in base64 format to verify the url. + // +kubebuilder:example:="YWFhCg==" + CABundle []byte `json:"caBundle,omitempty"` } -type DataSourceContainerRegistry struct { - Image string `json:"image"` - ImagePullSecret ImagePullSecret `json:"imagePullSecret"` - CABundle []byte `json:"caBundle"` +type ImagePullSecret struct { + // A name of the secret containing registry credentials. + Name string `json:"name,omitempty"` + // A namespace where imagePullSecret is located. + Namespace string `json:"namespace,omitempty"` } -type ImagePullSecret struct { - Name string `json:"name"` - Namespace string `json:"namespace"` +type ImagePullSecretName struct { + // A name of the secret containing registry credentials which must be located in the same namespace. + Name string `json:"name,omitempty"` } type Checksum struct { - MD5 string `json:"md5,omitempty"` + // +kubebuilder:example:="f3b59bed9f91e32fac1210184fcff6f5" + // +kubebuilder:validation:Pattern="^[0-9a-fA-F]{32}$" + // +kubebuilder:validation:MinLength:=32 + // +kubebuilder:validation:MaxLength:=32 + MD5 string `json:"md5,omitempty"` + // +kubebuilder:example:="78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5" + // +kubebuilder:validation:Pattern="^[0-9a-fA-F]{64}$" + // +kubebuilder:validation:MinLength:=64 + // +kubebuilder:validation:MaxLength:=64 SHA256 string `json:"sha256,omitempty"` } +// The type of an origin of the image. Options are: +// +// * `HTTP` — create an image from a file published on http/https service at a given url +// * `ContainerImage` — create the image from image stored in container registry. +// * `ObjectRef` — fill the disk from another existing resource. +// * `Upload` — fill the image with data, uploaded by user via the special interface. +// +// +kubebuilder:validation:Enum:={HTTP,ContainerImage,ObjectRef,Upload} type DataSourceType string const ( diff --git a/api/core/v1alpha2/image_status.go b/api/core/v1alpha2/image_status.go index 0d5662a24..ee764f73f 100644 --- a/api/core/v1alpha2/image_status.go +++ b/api/core/v1alpha2/image_status.go @@ -16,8 +16,6 @@ limitations under the License. package v1alpha2 -import "k8s.io/apimachinery/pkg/types" - type ImagePhase string const ( @@ -30,41 +28,41 @@ const ( ImageLost ImagePhase = "PVCLost" ) -type ImageStatus struct { - DownloadSpeed *StatusSpeed `json:"downloadSpeed"` - Size ImageStatusSize `json:"size"` - Format string `json:"format,omitempty"` - CDROM bool `json:"cdrom"` - Target ImageStatusTarget `json:"target"` - Phase ImagePhase `json:"phase,omitempty"` - Progress string `json:"progress,omitempty"` - SourceUID *types.UID `json:"sourceUID,omitempty"` - // Deprecated: use ImageUploadURLs instead. - UploadCommand string `json:"uploadCommand,omitempty"` - ImageUploadURLs *ImageUploadURLs `json:"imageUploadURLs,omitempty"` -} - type ImageUploadURLs struct { - External string `json:"external,omitempty"` + // Command to upload the image using `Ingress` from outside the cluster. + External string `json:"external,omitempty"` + // Command to upload the image using `Service` within the cluster. InCluster string `json:"inCluster,omitempty"` } +// Image download speed from an external source. Appears only during the `Provisioning` phase. type StatusSpeed struct { - Avg string `json:"avg,omitempty"` - AvgBytes string `json:"avgBytes,omitempty"` - Current string `json:"current,omitempty"` + // Average download speed. + // +kubebuilder:example:="1 Mbps" + Avg string `json:"avg,omitempty"` + // Average download speed in bytes per second. + // +kubebuilder:example:=1012345 + AvgBytes string `json:"avgBytes,omitempty"` + // Current download speed. + // +kubebuilder:example:="5 Mbps" + Current string `json:"current,omitempty"` + // Current download speed in bytes per second. + // +kubebuilder:example:=5123456 CurrentBytes string `json:"currentBytes,omitempty"` } +// Discovered sizes of the image. type ImageStatusSize struct { - Stored string `json:"stored,omitempty"` - StoredBytes string `json:"storedBytes,omitempty"` - Unpacked string `json:"unpacked,omitempty"` + // Image size in human-readable format. + // +kubebuilder:example:="199M" + Stored string `json:"stored,omitempty"` + // Image size in bytes. + // +kubebuilder:example:=199001234 + StoredBytes string `json:"storedBytes,omitempty"` + // Unpacked image size in human-readable format. + // +kubebuilder:example:="1G" + Unpacked string `json:"unpacked,omitempty"` + // Unpacked image size in bytes. + // +kubebuilder:example:=1000000234 UnpackedBytes string `json:"unpackedBytes,omitempty"` } - -type ImageStatusTarget struct { - RegistryURL string `json:"registryURL,omitempty"` - // FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim - PersistentVolumeClaim string `json:"persistentVolumeClaimName,omitempty"` -} diff --git a/api/core/v1alpha2/virtual_disk.go b/api/core/v1alpha2/virtual_disk.go index f64ff92eb..c7275c7da 100644 --- a/api/core/v1alpha2/virtual_disk.go +++ b/api/core/v1alpha2/virtual_disk.go @@ -75,10 +75,22 @@ type AttachedVirtualMachine struct { } type VirtualDiskDataSource struct { - Type DataSourceType `json:"type,omitempty"` - HTTP *DataSourceHTTP `json:"http,omitempty"` - ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` - ObjectRef *VirtualDiskObjectRef `json:"objectRef,omitempty"` + Type DataSourceType `json:"type,omitempty"` + HTTP *DataSourceHTTP `json:"http,omitempty"` + ContainerImage *VirtualDiskContainerImage `json:"containerImage,omitempty"` + ObjectRef *VirtualDiskObjectRef `json:"objectRef,omitempty"` +} + +// Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed. +type VirtualDiskContainerImage struct { + // The container registry address of an image. + // +kubebuilder:example:="registry.example.com/images/slackware:15" + // +kubebuilder:validation:Pattern:=`^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$` + Image string `json:"image"` + ImagePullSecret ImagePullSecretName `json:"imagePullSecret,omitempty"` + // The CA chain in base64 format to verify the container registry. + // +kubebuilder:example:="YWFhCg==" + CABundle []byte `json:"caBundle,omitempty"` } type VirtualDiskObjectRef struct { diff --git a/api/core/v1alpha2/virtual_image.go b/api/core/v1alpha2/virtual_image.go index 9e3d25099..0ffdfa4ac 100644 --- a/api/core/v1alpha2/virtual_image.go +++ b/api/core/v1alpha2/virtual_image.go @@ -18,6 +18,7 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" ) const ( @@ -25,8 +26,24 @@ const ( VirtualImageResource = "virtualimages" ) -// VirtualImage is an image for virtual machines available in the particular namespace. +// This resource describes a virtual disk image or installation image (iso) that can be used as a data source for new `VirtualDisks` or can be mounted in `Virtuals`. +// > This resource cannot be modified once it has been created. +// +// A container image is created under the hood of this resource, which is stored in a dedicated deckhouse virtualization container registy (DVCR) or PVC, into which the data from the source is filled. // +genclient +// +kubebuilder:object:root=true +// +kubebuilder:metadata:labels={heritage=deckhouse,module=virtualization} +// +kubebuilder:resource:categories={virtualization,all},scope=Namespaced,shortName={vi,vis},singular=virtualimage +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="CDROM",type=boolean,JSONPath=`.status.cdrom` +// +kubebuilder:printcolumn:name="Progress",type=string,JSONPath=`.status.progress` +// +kubebuilder:printcolumn:name="StoredSize",type=string,JSONPath=`.status.size.stored`,priority=1 +// +kubebuilder:printcolumn:name="UnpackedSize",type=string,JSONPath=`.status.size.unpacked`,priority=1 +// +kubebuilder:printcolumn:name="Registry URL",type=string,JSONPath=`.status.target.registryURL`,priority=1 +// +kubebuilder:printcolumn:name="TargetPVC",type=string,JSONPath=`.status.target.persistentVolumeClaimName`,priority=1 +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:validation:XValidation:rule="self.metadata.name.size() <= 128",message="The name must be no longer than 128 characters." // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type VirtualImage struct { metav1.TypeMeta `json:",inline"` @@ -50,30 +67,86 @@ type VirtualImageList struct { } type VirtualImageSpec struct { + // +kubebuilder:default:=ContainerRegistry Storage StorageType `json:"storage"` - PersistentVolumeClaim VirtualImagePersistentVolumeClaim `json:"persistentVolumeClaim"` + PersistentVolumeClaim VirtualImagePersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"` DataSource VirtualImageDataSource `json:"dataSource"` } type VirtualImageStatus struct { - ImageStatus `json:",inline"` - Conditions []metav1.Condition `json:"conditions,omitempty"` - ObservedGeneration int64 `json:"observedGeneration,omitempty"` - StorageClassName string `json:"storageClassName,omitempty"` + // Image download speed from an external source. Appears only during the `Provisioning` phase. + DownloadSpeed *StatusSpeed `json:"downloadSpeed,omitempty"` + // Discovered sizes of the image. + Size ImageStatusSize `json:"size,omitempty"` + // Discovered format of the image. + Format string `json:"format,omitempty"` + // Whether the image is a format that is supposed to be mounted as a cdrom, such as iso and so on. + CDROM bool `json:"cdrom,omitempty"` + // Current status of `ClusterVirtualImage` resource: + // * Pending - The resource has been created and is on a waiting queue. + // * Provisioning - The process of resource creation (copying/downloading/building the image) is in progress. + // * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. + // * Ready - The resource is created and ready to use. + // * Failed - There was a problem when creating a resource. + // * Terminating - The process of resource deletion is in progress. + // * PVCLost - The child PVC of the resource is missing. The resource cannot be used. + // +kubebuilder:validation:Enum:={Pending,Provisioning,WaitForUserUpload,Ready,Failed,Terminating,PVCLost} + Phase ImagePhase `json:"phase,omitempty"` + // Progress of copying an image from source to DVCR. + Progress string `json:"progress,omitempty"` + // Deprecated. Use imageUploadURLs instead. + UploadCommand string `json:"uploadCommand,omitempty"` + ImageUploadURLs *ImageUploadURLs `json:"imageUploadURLs,omitempty"` + Target VirtualImageStatusTarget `json:"target,omitempty"` + // The UID of the source (`VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`) used when creating the virtual image. + SourceUID *types.UID `json:"sourceUID,omitempty"` + // The latest available observations of an object's current state. + Conditions []metav1.Condition `json:"conditions,omitempty"` + // The generation last processed by the controller. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // The name of the StorageClass used by the PersistentVolumeClaim if `Kubernetes` storage type used. + StorageClassName string `json:"storageClassName,omitempty"` } +type VirtualImageStatusTarget struct { + // Created image in DVCR. + // +kubebuilder:example:="dvcr..svc/vi//:latest" + RegistryURL string `json:"registryURL,omitempty"` + // Created PersistentVolumeClaim name for Kubernetes storage. + PersistentVolumeClaim string `json:"persistentVolumeClaimName,omitempty"` +} + +// +kubebuilder:validation:XValidation:rule="self.type == 'HTTP' ? has(self.http) && !has(self.containerImage) && !has(self.objectRef) : true",message="HTTP requires http and cannot have ContainerImage or ObjectRef" +// +kubebuilder:validation:XValidation:rule="self.type == 'ContainerImage' ? has(self.containerImage) && !has(self.http) && !has(self.objectRef) : true",message="ContainerImage requires containerImage and cannot have HTTP or ObjectRef" +// +kubebuilder:validation:XValidation:rule="self.type == 'ObjectRef' ? has(self.objectRef) && !has(self.http) && !has(self.containerImage) : true",message="ObjectRef requires objectRef and cannot have HTTP or ContainerImage" type VirtualImageDataSource struct { - Type DataSourceType `json:"type,omitempty"` - HTTP *DataSourceHTTP `json:"http,omitempty"` - ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` - ObjectRef *VirtualImageObjectRef `json:"objectRef,omitempty"` + Type DataSourceType `json:"type,omitempty"` + HTTP *DataSourceHTTP `json:"http,omitempty"` + ContainerImage *VirtualImageContainerImage `json:"containerImage,omitempty"` + ObjectRef *VirtualImageObjectRef `json:"objectRef,omitempty"` +} + +// Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed. +type VirtualImageContainerImage struct { + // The container registry address of an image. + // +kubebuilder:example:="registry.example.com/images/slackware:15" + // +kubebuilder:validation:Pattern:=`^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$` + Image string `json:"image"` + ImagePullSecret ImagePullSecretName `json:"imagePullSecret,omitempty"` + // The CA chain in base64 format to verify the container registry. + // +kubebuilder:example:="YWFhCg==" + CABundle []byte `json:"caBundle,omitempty"` } +// Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk` to create an image. type VirtualImageObjectRef struct { - Kind VirtualImageObjectRefKind `json:"kind,omitempty"` - Name string `json:"name,omitempty"` + // A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. + Kind VirtualImageObjectRefKind `json:"kind"` + // A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. + Name string `json:"name"` } +// +kubebuilder:validation:Enum:={ClusterVirtualImage,VirtualImage,VirtualDisk} type VirtualImageObjectRefKind string const ( @@ -82,6 +155,11 @@ const ( VirtualImageObjectRefKindVirtualDisk VirtualImageObjectRefKind = "VirtualDisk" ) +// Storage type to store the image for current virtualization setup. +// +// * `ContainerRegistry` — use a dedicated deckhouse virtualization container registry (DVCR). In this case, images will be downloaded and injected to a container, then pushed to a DVCR (shipped with the virtualization module). +// * `Kubernetes` - use a Persistent Volume Claim (PVC). +// +kubebuilder:validation:Enum:={ContainerRegistry,Kubernetes} type StorageType string const ( diff --git a/api/core/v1alpha2/zz_generated.deepcopy.go b/api/core/v1alpha2/zz_generated.deepcopy.go index 931d86fef..137e594a6 100644 --- a/api/core/v1alpha2/zz_generated.deepcopy.go +++ b/api/core/v1alpha2/zz_generated.deepcopy.go @@ -177,6 +177,28 @@ func (in *ClusterVirtualImage) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterVirtualImageContainerImage) DeepCopyInto(out *ClusterVirtualImageContainerImage) { + *out = *in + out.ImagePullSecret = in.ImagePullSecret + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageContainerImage. +func (in *ClusterVirtualImageContainerImage) DeepCopy() *ClusterVirtualImageContainerImage { + if in == nil { + return nil + } + out := new(ClusterVirtualImageContainerImage) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterVirtualImageDataSource) DeepCopyInto(out *ClusterVirtualImageDataSource) { *out = *in @@ -187,7 +209,7 @@ func (in *ClusterVirtualImageDataSource) DeepCopyInto(out *ClusterVirtualImageDa } if in.ContainerImage != nil { in, out := &in.ContainerImage, &out.ContainerImage - *out = new(DataSourceContainerRegistry) + *out = new(ClusterVirtualImageContainerImage) (*in).DeepCopyInto(*out) } if in.ObjectRef != nil { @@ -277,7 +299,17 @@ func (in *ClusterVirtualImageSpec) DeepCopy() *ClusterVirtualImageSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterVirtualImageStatus) DeepCopyInto(out *ClusterVirtualImageStatus) { *out = *in - in.ImageStatus.DeepCopyInto(&out.ImageStatus) + if in.DownloadSpeed != nil { + in, out := &in.DownloadSpeed, &out.DownloadSpeed + *out = new(StatusSpeed) + **out = **in + } + out.Size = in.Size + if in.SourceUID != nil { + in, out := &in.SourceUID, &out.SourceUID + *out = new(types.UID) + **out = **in + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]v1.Condition, len(*in)) @@ -285,6 +317,12 @@ func (in *ClusterVirtualImageStatus) DeepCopyInto(out *ClusterVirtualImageStatus (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ImageUploadURLs != nil { + in, out := &in.ImageUploadURLs, &out.ImageUploadURLs + *out = new(ImageUploadURLs) + **out = **in + } + out.Target = in.Target return } @@ -298,6 +336,22 @@ func (in *ClusterVirtualImageStatus) DeepCopy() *ClusterVirtualImageStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterVirtualImageStatusTarget) DeepCopyInto(out *ClusterVirtualImageStatusTarget) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageStatusTarget. +func (in *ClusterVirtualImageStatusTarget) DeepCopy() *ClusterVirtualImageStatusTarget { + if in == nil { + return nil + } + out := new(ClusterVirtualImageStatusTarget) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CpuDiscovery) DeepCopyInto(out *CpuDiscovery) { *out = *in @@ -341,41 +395,19 @@ func (in *CpuFeatures) DeepCopy() *CpuFeatures { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataSourceContainerRegistry) DeepCopyInto(out *DataSourceContainerRegistry) { - *out = *in - out.ImagePullSecret = in.ImagePullSecret - if in.CABundle != nil { - in, out := &in.CABundle, &out.CABundle - *out = make([]byte, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceContainerRegistry. -func (in *DataSourceContainerRegistry) DeepCopy() *DataSourceContainerRegistry { - if in == nil { - return nil - } - out := new(DataSourceContainerRegistry) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DataSourceHTTP) DeepCopyInto(out *DataSourceHTTP) { *out = *in - if in.CABundle != nil { - in, out := &in.CABundle, &out.CABundle - *out = make([]byte, len(*in)) - copy(*out, *in) - } if in.Checksum != nil { in, out := &in.Checksum, &out.Checksum *out = new(Checksum) **out = **in } + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } return } @@ -438,34 +470,17 @@ func (in *ImagePullSecret) DeepCopy() *ImagePullSecret { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ImageStatus) DeepCopyInto(out *ImageStatus) { +func (in *ImagePullSecretName) DeepCopyInto(out *ImagePullSecretName) { *out = *in - if in.DownloadSpeed != nil { - in, out := &in.DownloadSpeed, &out.DownloadSpeed - *out = new(StatusSpeed) - **out = **in - } - out.Size = in.Size - out.Target = in.Target - if in.SourceUID != nil { - in, out := &in.SourceUID, &out.SourceUID - *out = new(types.UID) - **out = **in - } - if in.ImageUploadURLs != nil { - in, out := &in.ImageUploadURLs, &out.ImageUploadURLs - *out = new(ImageUploadURLs) - **out = **in - } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatus. -func (in *ImageStatus) DeepCopy() *ImageStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullSecretName. +func (in *ImagePullSecretName) DeepCopy() *ImagePullSecretName { if in == nil { return nil } - out := new(ImageStatus) + out := new(ImagePullSecretName) in.DeepCopyInto(out) return out } @@ -486,22 +501,6 @@ func (in *ImageStatusSize) DeepCopy() *ImageStatusSize { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ImageStatusTarget) DeepCopyInto(out *ImageStatusTarget) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatusTarget. -func (in *ImageStatusTarget) DeepCopy() *ImageStatusTarget { - if in == nil { - return nil - } - out := new(ImageStatusTarget) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageUploadURLs) DeepCopyInto(out *ImageUploadURLs) { *out = *in @@ -889,6 +888,28 @@ func (in *VirtualDisk) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualDiskContainerImage) DeepCopyInto(out *VirtualDiskContainerImage) { + *out = *in + out.ImagePullSecret = in.ImagePullSecret + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskContainerImage. +func (in *VirtualDiskContainerImage) DeepCopy() *VirtualDiskContainerImage { + if in == nil { + return nil + } + out := new(VirtualDiskContainerImage) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualDiskDataSource) DeepCopyInto(out *VirtualDiskDataSource) { *out = *in @@ -899,7 +920,7 @@ func (in *VirtualDiskDataSource) DeepCopyInto(out *VirtualDiskDataSource) { } if in.ContainerImage != nil { in, out := &in.ContainerImage, &out.ContainerImage - *out = new(DataSourceContainerRegistry) + *out = new(VirtualDiskContainerImage) (*in).DeepCopyInto(*out) } if in.ObjectRef != nil { @@ -1243,6 +1264,28 @@ func (in *VirtualImage) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualImageContainerImage) DeepCopyInto(out *VirtualImageContainerImage) { + *out = *in + out.ImagePullSecret = in.ImagePullSecret + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageContainerImage. +func (in *VirtualImageContainerImage) DeepCopy() *VirtualImageContainerImage { + if in == nil { + return nil + } + out := new(VirtualImageContainerImage) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualImageDataSource) DeepCopyInto(out *VirtualImageDataSource) { *out = *in @@ -1253,7 +1296,7 @@ func (in *VirtualImageDataSource) DeepCopyInto(out *VirtualImageDataSource) { } if in.ContainerImage != nil { in, out := &in.ContainerImage, &out.ContainerImage - *out = new(DataSourceContainerRegistry) + *out = new(VirtualImageContainerImage) (*in).DeepCopyInto(*out) } if in.ObjectRef != nil { @@ -1365,7 +1408,23 @@ func (in *VirtualImageSpec) DeepCopy() *VirtualImageSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualImageStatus) DeepCopyInto(out *VirtualImageStatus) { *out = *in - in.ImageStatus.DeepCopyInto(&out.ImageStatus) + if in.DownloadSpeed != nil { + in, out := &in.DownloadSpeed, &out.DownloadSpeed + *out = new(StatusSpeed) + **out = **in + } + out.Size = in.Size + if in.ImageUploadURLs != nil { + in, out := &in.ImageUploadURLs, &out.ImageUploadURLs + *out = new(ImageUploadURLs) + **out = **in + } + out.Target = in.Target + if in.SourceUID != nil { + in, out := &in.SourceUID, &out.SourceUID + *out = new(types.UID) + **out = **in + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]v1.Condition, len(*in)) @@ -1386,6 +1445,22 @@ func (in *VirtualImageStatus) DeepCopy() *VirtualImageStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualImageStatusTarget) DeepCopyInto(out *VirtualImageStatusTarget) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageStatusTarget. +func (in *VirtualImageStatusTarget) DeepCopy() *VirtualImageStatusTarget { + if in == nil { + return nil + } + out := new(VirtualImageStatusTarget) + 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 diff --git a/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go b/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go index 2f5f88e06..94f516741 100644 --- a/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go +++ b/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go @@ -41,21 +41,21 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization/api/core/v1alpha2.CPUStatus": schema_virtualization_api_core_v1alpha2_CPUStatus(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.Checksum": schema_virtualization_api_core_v1alpha2_Checksum(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImage": schema_virtualization_api_core_v1alpha2_ClusterVirtualImage(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageContainerImage": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageContainerImage(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageDataSource": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageDataSource(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageList": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageList(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageObjectRef": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageObjectRef(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageSpec": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageSpec(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageStatus": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageStatus(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageStatusTarget": schema_virtualization_api_core_v1alpha2_ClusterVirtualImageStatusTarget(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.CpuDiscovery": schema_virtualization_api_core_v1alpha2_CpuDiscovery(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.CpuFeatures": schema_virtualization_api_core_v1alpha2_CpuFeatures(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry": schema_virtualization_api_core_v1alpha2_DataSourceContainerRegistry(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP": schema_virtualization_api_core_v1alpha2_DataSourceHTTP(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.DiskTarget": schema_virtualization_api_core_v1alpha2_DiskTarget(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.Disruptions": schema_virtualization_api_core_v1alpha2_Disruptions(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecret": schema_virtualization_api_core_v1alpha2_ImagePullSecret(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatus": schema_virtualization_api_core_v1alpha2_ImageStatus(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecretName": schema_virtualization_api_core_v1alpha2_ImagePullSecretName(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize": schema_virtualization_api_core_v1alpha2_ImageStatusSize(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget": schema_virtualization_api_core_v1alpha2_ImageStatusTarget(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs": schema_virtualization_api_core_v1alpha2_ImageUploadURLs(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.MemoryMinMax": schema_virtualization_api_core_v1alpha2_MemoryMinMax(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.MemorySpec": schema_virtualization_api_core_v1alpha2_MemorySpec(ref), @@ -75,6 +75,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization/api/core/v1alpha2.VMAffinity": schema_virtualization_api_core_v1alpha2_VMAffinity(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VMBDAObjectRef": schema_virtualization_api_core_v1alpha2_VMBDAObjectRef(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDisk": schema_virtualization_api_core_v1alpha2_VirtualDisk(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskContainerImage": schema_virtualization_api_core_v1alpha2_VirtualDiskContainerImage(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskDataSource": schema_virtualization_api_core_v1alpha2_VirtualDiskDataSource(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskList": schema_virtualization_api_core_v1alpha2_VirtualDiskList(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskObjectRef": schema_virtualization_api_core_v1alpha2_VirtualDiskObjectRef(ref), @@ -88,12 +89,14 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskStatsCreationDuration": schema_virtualization_api_core_v1alpha2_VirtualDiskStatsCreationDuration(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskStatus": schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImage": schema_virtualization_api_core_v1alpha2_VirtualImage(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageContainerImage": schema_virtualization_api_core_v1alpha2_VirtualImageContainerImage(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageDataSource": schema_virtualization_api_core_v1alpha2_VirtualImageDataSource(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageList": schema_virtualization_api_core_v1alpha2_VirtualImageList(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageObjectRef": schema_virtualization_api_core_v1alpha2_VirtualImageObjectRef(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImagePersistentVolumeClaim": schema_virtualization_api_core_v1alpha2_VirtualImagePersistentVolumeClaim(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageSpec": schema_virtualization_api_core_v1alpha2_VirtualImageSpec(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageStatus": schema_virtualization_api_core_v1alpha2_VirtualImageStatus(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageStatusTarget": schema_virtualization_api_core_v1alpha2_VirtualImageStatusTarget(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachine": schema_virtualization_api_core_v1alpha2_VirtualMachine(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineAndPodAffinity": schema_virtualization_api_core_v1alpha2_VirtualMachineAndPodAffinity(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineAndPodAffinityTerm": schema_virtualization_api_core_v1alpha2_VirtualMachineAndPodAffinityTerm(ref), @@ -932,7 +935,7 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImage(ref common.Refe return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ClusterVirtualImage is a cluster wide available image for virtual machines.", + Description: "Describes a virtual disk image that can be used as a data source for new `VirtualDisks` or an installation image (iso) to be mounted in `Virtuals` directly. This resource type is available for all namespaces in the cluster.\n\n> This resource cannot be modified once it has been created.\n\nA container image is created under the hood of this resource, which is stored in a dedicated deckhouse virtualization container registry (DVCR).", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -976,16 +979,55 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImage(ref common.Refe } } +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageContainerImage(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "image": { + SchemaProps: spec.SchemaProps{ + Description: "The container registry address of an image.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullSecret": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecret"), + }, + }, + "caBundle": { + SchemaProps: spec.SchemaProps{ + Description: "The CA chain in base64 format to verify the container registry.", + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"image"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecret"}, + } +} + func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "An origin of the image.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "type": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "http": { @@ -995,7 +1037,7 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageDataSource(ref c }, "containerImage": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageContainerImage"), }, }, "objectRef": { @@ -1004,10 +1046,11 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageDataSource(ref c }, }, }, + Required: []string{"type"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageObjectRef", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageContainerImage", "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageObjectRef", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP"}, } } @@ -1065,27 +1108,33 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageObjectRef(ref co return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk` to create an image.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "name": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "namespace": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "A namespace where `VirtualImage` or `VirtualDisk` is located.", + Type: []string{"string"}, + Format: "", }, }, }, + Required: []string{"kind", "name"}, }, }, } @@ -1120,67 +1169,56 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageStatus(ref commo Properties: map[string]spec.Schema{ "downloadSpeed": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed"), + Description: "Image download speed from an external source. Appears only during the `Provisioning` phase.", + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed"), }, }, "size": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), + Description: "Discovered sizes of the image.", + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), }, }, "format": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Discovered format of the image.", + Type: []string{"string"}, + Format: "", }, }, "cdrom": { SchemaProps: spec.SchemaProps{ - Default: false, - Type: []string{"boolean"}, - Format: "", - }, - }, - "target": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget"), + Description: "Whether the image is a format that is supposed to be mounted as a cdrom, such as iso and so on.", + Type: []string{"boolean"}, + Format: "", }, }, "phase": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Current status of `ClusterVirtualImage` resource: * Pending - The resource has been created and is on a waiting queue. * Provisioning - The process of resource creation (copying/downloading/building the image) is in progress. * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. * Ready - The resource is created and ready to use. * Failed - There was a problem when creating a resource. * Terminating - The process of resource deletion is in progress.", + Type: []string{"string"}, + Format: "", }, }, "progress": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Progress of copying an image from source to DVCR. Appears only during the `Provisioning' phase.", + Type: []string{"string"}, + Format: "", }, }, "sourceUID": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "uploadCommand": { - SchemaProps: spec.SchemaProps{ - Description: "Deprecated: use ImageUploadURLs instead.", + Description: "The UID of the source (`VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`) used when creating the cluster virtual image.", Type: []string{"string"}, Format: "", }, }, - "imageUploadURLs": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs"), - }, - }, "conditions": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "The latest available observations of an object's current state.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1193,16 +1231,53 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageStatus(ref commo }, "observedGeneration": { SchemaProps: spec.SchemaProps{ - Type: []string{"integer"}, - Format: "int64", + Description: "The generation last processed by the controller.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "uploadCommand": { + SchemaProps: spec.SchemaProps{ + Description: "Deprecated. Use imageUploadURLs instead.", + Type: []string{"string"}, + Format: "", + }, + }, + "imageUploadURLs": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs"), + }, + }, + "target": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageStatusTarget"), }, }, }, - Required: []string{"downloadSpeed", "size", "cdrom", "target"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs", "github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageStatusTarget", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs", "github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"}, + } +} + +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageStatusTarget(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "registryURL": { + SchemaProps: spec.SchemaProps{ + Description: "Created image in DVCR.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, } } @@ -1270,66 +1345,36 @@ func schema_virtualization_api_core_v1alpha2_CpuFeatures(ref common.ReferenceCal } } -func schema_virtualization_api_core_v1alpha2_DataSourceContainerRegistry(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_DataSourceHTTP(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Fill the image with data from some external url. Supported schemas are:\n\n* http * https\n\nFor https schema there is an option to skip TLS verification.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ - "image": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "imagePullSecret": { + "checksum": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecret"), + Description: "A checksum of the file, provided by the url, to verify if it was downloaded correctly or wasn't changed. The file should match all specified checksums.", + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.Checksum"), }, }, - "caBundle": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "byte", - }, - }, - }, - Required: []string{"image", "imagePullSecret", "caBundle"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecret"}, - } -} - -func schema_virtualization_api_core_v1alpha2_DataSourceHTTP(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ "url": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "The http url with an image. The following formats are supported: * qcow2 * vmdk * vdi * iso * raw these formats can also be compressed with the following formats: * gz * xz", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "caBundle": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "byte", - }, - }, - "checksum": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.Checksum"), + Description: "The CA chain in base64 format to verify the url.", + Type: []string{"string"}, + Format: "byte", }, }, }, - Required: []string{"url", "caBundle"}, + Required: []string{"url"}, }, }, Dependencies: []string{ @@ -1382,97 +1427,40 @@ func schema_virtualization_api_core_v1alpha2_ImagePullSecret(ref common.Referenc Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "A name of the secret containing registry credentials.", + Type: []string{"string"}, + Format: "", }, }, "namespace": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "A namespace where imagePullSecret is located.", + Type: []string{"string"}, + Format: "", }, }, }, - Required: []string{"name", "namespace"}, }, }, } } -func schema_virtualization_api_core_v1alpha2_ImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ImagePullSecretName(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "downloadSpeed": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed"), - }, - }, - "size": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), - }, - }, - "format": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "cdrom": { - SchemaProps: spec.SchemaProps{ - Default: false, - Type: []string{"boolean"}, - Format: "", - }, - }, - "target": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget"), - }, - }, - "phase": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "progress": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "sourceUID": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "uploadCommand": { + "name": { SchemaProps: spec.SchemaProps{ - Description: "Deprecated: use ImageUploadURLs instead.", + Description: "A name of the secret containing registry credentials which must be located in the same namespace.", Type: []string{"string"}, Format: "", }, }, - "imageUploadURLs": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs"), - }, - }, }, - Required: []string{"downloadSpeed", "size", "cdrom", "target"}, }, }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs", "github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed"}, } } @@ -1480,53 +1468,33 @@ func schema_virtualization_api_core_v1alpha2_ImageStatusSize(ref common.Referenc return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Discovered sizes of the image.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "stored": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Image size in human-readable format.", + Type: []string{"string"}, + Format: "", }, }, "storedBytes": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Image size in bytes.", + Type: []string{"string"}, + Format: "", }, }, "unpacked": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Unpacked image size in human-readable format.", + Type: []string{"string"}, + Format: "", }, }, "unpackedBytes": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_ImageStatusTarget(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "registryURL": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "persistentVolumeClaimName": { - SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", + Description: "Unpacked image size in bytes.", Type: []string{"string"}, Format: "", }, @@ -1545,14 +1513,16 @@ func schema_virtualization_api_core_v1alpha2_ImageUploadURLs(ref common.Referenc Properties: map[string]spec.Schema{ "external": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Command to upload the image using `Ingress` from outside the cluster.", + Type: []string{"string"}, + Format: "", }, }, "inCluster": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Command to upload the image using `Service` within the cluster.", + Type: []string{"string"}, + Format: "", }, }, }, @@ -1970,30 +1940,35 @@ func schema_virtualization_api_core_v1alpha2_StatusSpeed(ref common.ReferenceCal return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Image download speed from an external source. Appears only during the `Provisioning` phase.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "avg": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Average download speed.", + Type: []string{"string"}, + Format: "", }, }, "avgBytes": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Average download speed in bytes per second.", + Type: []string{"string"}, + Format: "", }, }, "current": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Current download speed.", + Type: []string{"string"}, + Format: "", }, }, "currentBytes": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Current download speed in bytes per second.", + Type: []string{"string"}, + Format: "", }, }, }, @@ -2163,6 +2138,43 @@ func schema_virtualization_api_core_v1alpha2_VirtualDisk(ref common.ReferenceCal } } +func schema_virtualization_api_core_v1alpha2_VirtualDiskContainerImage(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "image": { + SchemaProps: spec.SchemaProps{ + Description: "The container registry address of an image.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullSecret": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecretName"), + }, + }, + "caBundle": { + SchemaProps: spec.SchemaProps{ + Description: "The CA chain in base64 format to verify the container registry.", + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"image"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecretName"}, + } +} + func schema_virtualization_api_core_v1alpha2_VirtualDiskDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -2182,7 +2194,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskDataSource(ref common.Re }, "containerImage": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskContainerImage"), }, }, "objectRef": { @@ -2194,7 +2206,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskDataSource(ref common.Re }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskObjectRef"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskContainerImage", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskObjectRef"}, } } @@ -2667,7 +2679,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualImage(ref common.ReferenceCa return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "VirtualImage is an image for virtual machines available in the particular namespace.", + Description: "This resource describes a virtual disk image or installation image (iso) that can be used as a data source for new `VirtualDisks` or can be mounted in `Virtuals`. > This resource cannot be modified once it has been created.\n\nA container image is created under the hood of this resource, which is stored in a dedicated deckhouse virtualization container registy (DVCR) or PVC, into which the data from the source is filled.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -2711,6 +2723,43 @@ func schema_virtualization_api_core_v1alpha2_VirtualImage(ref common.ReferenceCa } } +func schema_virtualization_api_core_v1alpha2_VirtualImageContainerImage(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "image": { + SchemaProps: spec.SchemaProps{ + Description: "The container registry address of an image.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullSecret": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecretName"), + }, + }, + "caBundle": { + SchemaProps: spec.SchemaProps{ + Description: "The CA chain in base64 format to verify the container registry.", + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"image"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.ImagePullSecretName"}, + } +} + func schema_virtualization_api_core_v1alpha2_VirtualImageDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -2730,7 +2779,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageDataSource(ref common.R }, "containerImage": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageContainerImage"), }, }, "objectRef": { @@ -2742,7 +2791,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageDataSource(ref common.R }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageObjectRef"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageContainerImage", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageObjectRef"}, } } @@ -2800,21 +2849,27 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageObjectRef(ref common.Re return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk` to create an image.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "name": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, }, + Required: []string{"kind", "name"}, }, }, } @@ -2864,7 +2919,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageSpec(ref common.Referen }, }, }, - Required: []string{"storage", "persistentVolumeClaim", "dataSource"}, + Required: []string{"storage", "dataSource"}, }, }, Dependencies: []string{ @@ -2880,55 +2935,48 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageStatus(ref common.Refer Properties: map[string]spec.Schema{ "downloadSpeed": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed"), + Description: "Image download speed from an external source. Appears only during the `Provisioning` phase.", + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed"), }, }, "size": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), + Description: "Discovered sizes of the image.", + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), }, }, "format": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Discovered format of the image.", + Type: []string{"string"}, + Format: "", }, }, "cdrom": { SchemaProps: spec.SchemaProps{ - Default: false, - Type: []string{"boolean"}, - Format: "", - }, - }, - "target": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget"), + Description: "Whether the image is a format that is supposed to be mounted as a cdrom, such as iso and so on.", + Type: []string{"boolean"}, + Format: "", }, }, "phase": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Current status of `ClusterVirtualImage` resource: * Pending - The resource has been created and is on a waiting queue. * Provisioning - The process of resource creation (copying/downloading/building the image) is in progress. * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. * Ready - The resource is created and ready to use. * Failed - There was a problem when creating a resource. * Terminating - The process of resource deletion is in progress. * PVCLost - The child PVC of the resource is missing. The resource cannot be used.", + Type: []string{"string"}, + Format: "", }, }, "progress": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "sourceUID": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Progress of copying an image from source to DVCR.", + Type: []string{"string"}, + Format: "", }, }, "uploadCommand": { SchemaProps: spec.SchemaProps{ - Description: "Deprecated: use ImageUploadURLs instead.", + Description: "Deprecated. Use imageUploadURLs instead.", Type: []string{"string"}, Format: "", }, @@ -2938,9 +2986,23 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageStatus(ref common.Refer Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs"), }, }, + "target": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageStatusTarget"), + }, + }, + "sourceUID": { + SchemaProps: spec.SchemaProps{ + Description: "The UID of the source (`VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`) used when creating the virtual image.", + Type: []string{"string"}, + Format: "", + }, + }, "conditions": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "The latest available observations of an object's current state.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2953,22 +3015,49 @@ func schema_virtualization_api_core_v1alpha2_VirtualImageStatus(ref common.Refer }, "observedGeneration": { SchemaProps: spec.SchemaProps{ - Type: []string{"integer"}, - Format: "int64", + Description: "The generation last processed by the controller.", + Type: []string{"integer"}, + Format: "int64", }, }, "storageClassName": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "The name of the StorageClass used by the PersistentVolumeClaim if `Kubernetes` storage type used.", + Type: []string{"string"}, + Format: "", }, }, }, - Required: []string{"downloadSpeed", "size", "cdrom", "target"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs", "github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageUploadURLs", "github.com/deckhouse/virtualization/api/core/v1alpha2.StatusSpeed", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageStatusTarget", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImageStatusTarget(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "registryURL": { + SchemaProps: spec.SchemaProps{ + Description: "Created image in DVCR.", + Type: []string{"string"}, + Format: "", + }, + }, + "persistentVolumeClaimName": { + SchemaProps: spec.SchemaProps{ + Description: "Created PersistentVolumeClaim name for Kubernetes storage.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, } } diff --git a/api/scripts/update-codegen.sh b/api/scripts/update-codegen.sh index 8f13278a0..9350b274d 100755 --- a/api/scripts/update-codegen.sh +++ b/api/scripts/update-codegen.sh @@ -36,7 +36,9 @@ function source::settings { "VirtualMachineBlockDeviceAttachment" "VirtualMachineSnapshot" "VirtualMachineRestore" - "VirtualMachineOperation") + "VirtualMachineOperation" + "VirtualImage" + "ClusterVirtualImage") source "${CODEGEN_PKG}/kube_codegen.sh" } diff --git a/crds/clustervirtualimages.yaml b/crds/clustervirtualimages.yaml index c2a2300c0..6f64f5062 100644 --- a/crds/clustervirtualimages.yaml +++ b/crds/clustervirtualimages.yaml @@ -1,87 +1,152 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: clustervirtualimages.virtualization.deckhouse.io + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 labels: + backup.deckhouse.io/cluster-config: "true" heritage: deckhouse module: virtualization - backup.deckhouse.io/cluster-config: "true" + name: clustervirtualimages.virtualization.deckhouse.io spec: group: virtualization.deckhouse.io - scope: Cluster names: categories: - virtualization - plural: clustervirtualimages - singular: clustervirtualimage kind: ClusterVirtualImage + listKind: ClusterVirtualImageList + plural: clustervirtualimages shortNames: - cvi - cvis - preserveUnknownFields: false + singular: clustervirtualimage + scope: Cluster versions: - - name: v1alpha2 - served: true - storage: true + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .status.cdrom + name: CDROM + type: boolean + - jsonPath: .status.progress + name: Progress + type: string + - jsonPath: .status.size.stored + name: StoredSize + priority: 1 + type: string + - jsonPath: .status.size.unpacked + name: UnpackedSize + priority: 1 + type: string + - jsonPath: .status.target.registryURL + name: Registry URL + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 schema: openAPIV3Schema: - type: object - description: | + description: |- Describes a virtual disk image that can be used as a data source for new `VirtualDisks` or an installation image (iso) to be mounted in `Virtuals` directly. This resource type is available for all namespaces in the cluster. > This resource cannot be modified once it has been created. A container image is created under the hood of this resource, which is stored in a dedicated deckhouse virtualization container registry (DVCR). - required: - - spec - x-kubernetes-validations: - - rule: "self.metadata.name.size() <= 128" - message: "The name must be no longer than 128 characters." properties: - spec: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: type: object - required: - - dataSource + spec: properties: dataSource: - type: object - description: | - An origin of the image. - required: - - type + description: An origin of the image. properties: - type: - type: string - enum: - - "HTTP" - - "ContainerImage" - - "ObjectRef" - - "Upload" - description: | - The type of an origin of the image. Options are: - - * `HTTP` — create an image from a file published on http/https service at a given url - * `ContainerImage` — create the image from image stored in container registry. - * `ObjectRef` — fill the disk from another existing resource. - * `Upload` — fill the image with data, uploaded by user via the special interface. - http: + containerImage: + description: + Use an image stored in external container registry. + Only TLS enabled registries are supported. Use caBundle field + to provide custom CA chain if needed. + properties: + caBundle: + description: + The CA chain in base64 format to verify the container + registry. + example: YWFhCg== + format: byte + type: string + image: + description: The container registry address of an image. + example: registry.example.com/images/slackware:15 + pattern: ^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$ + type: string + imagePullSecret: + properties: + name: + description: + A name of the secret containing registry + credentials. + type: string + namespace: + description: A namespace where imagePullSecret is located. + type: string + type: object + required: + - image type: object - description: | + http: + description: |- Fill the image with data from some external url. Supported schemas are: * http * https For https schema there is an option to skip TLS verification. - required: - - url properties: - url: + caBundle: + description: The CA chain in base64 format to verify the url. + example: YWFhCg== + format: byte type: string - example: "https://mirror.example.com/images/slackware-15.qcow.gz" - # https://regex101.com/r/2zx8as/1 - pattern: ^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$ - description: | + checksum: + description: + A checksum of the file, provided by the url, + to verify if it was downloaded correctly or wasn't changed. + The file should match all specified checksums. + properties: + md5: + example: f3b59bed9f91e32fac1210184fcff6f5 + maxLength: 32 + minLength: 32 + pattern: ^[0-9a-fA-F]{32}$ + type: string + sha256: + example: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5 + maxLength: 64 + minLength: 64 + pattern: ^[0-9a-fA-F]{64}$ + type: string + type: object + url: + description: |- The http url with an image. The following formats are supported: * qcow2 * vmdk @@ -91,127 +156,101 @@ spec: these formats can also be compressed with the following formats: * gz * xz - caBundle: + example: https://mirror.example.com/images/slackware-15.qcow.gz + pattern: ^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$ type: string - format: byte - description: | - The CA chain in base64 format to verify the url. - example: | - YWFhCg== - checksum: - type: object - description: | - A checksum of the file, provided by the url, to verify if it was downloaded correctly or wasn't changed. The file should match all specified checksums. - properties: - md5: - description: "" - type: string - pattern: ^[0-9a-fA-F]{32}$ - minLength: 32 - maxLength: 32 - example: f3b59bed9f91e32fac1210184fcff6f5 - sha256: - description: "" - type: string - pattern: ^[0-9a-fA-F]{64}$ - minLength: 64 - maxLength: 64 - example: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5 - containerImage: - type: object required: - - image - description: | - Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed. - properties: - image: - type: string - example: "registry.example.com/images/slackware:15" - # https://regex101.com/r/NXfP8Y/1 - pattern: ^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$ - description: | - The container registry address of an image. - imagePullSecret: - type: object - properties: - name: - type: string - description: | - A name of the secret containing registry credentials. - namespace: - type: string - description: | - A namespace where imagePullSecret is located. - caBundle: - type: string - format: byte - description: | - The CA chain in base64 format to verify the container registry. - example: | - YWFhCg== - objectRef: + - url type: object - description: | - Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk` to create an image. - required: ["kind", "name"] - x-kubernetes-validations: - - rule: "self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' ? has(self.__namespace__) && size(self.__namespace__) > 0 : true" - message: The namespace is required for VirtualDisk and VirtualImage - - rule: "self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' ? has(self.__namespace__) && size(self.__namespace__) < 64 : true" - message: "The namespace must be no longer than 63 characters." + objectRef: + description: + Use an existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk` to create an image. properties: kind: - type: string - description: A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. + description: + A kind of existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk`. enum: - - "ClusterVirtualImage" - - "VirtualImage" - - "VirtualDisk" + - ClusterVirtualImage + - VirtualImage + - VirtualDisk + type: string name: + description: + A name of existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk`. type: string - description: | - A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. namespace: + description: + A namespace where `VirtualImage` or `VirtualDisk` + is located. type: string - description: | - A namespace where `VirtualImage` or `VirtualDisk` is located. - oneOf: - - properties: - type: - enum: ["HTTP"] - http: {} - required: ["http"] - - properties: - type: - enum: ["ContainerImage"] - containerImage: {} - required: ["containerImage"] - - properties: - type: - enum: ["ObjectRef"] - objectRef: {} - required: ["objectRef"] - - properties: - type: - enum: ["Upload"] - status: + required: + - kind + - name + type: object + x-kubernetes-validations: + - message: The namespace is required for VirtualDisk and VirtualImage + rule: + "self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' + ? has(self.__namespace__) && size(self.__namespace__) > 0 + : true" + - message: The namespace must be no longer than 63 characters. + rule: + "self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' + ? has(self.__namespace__) && size(self.__namespace__) < 64 + : true" + type: + description: |- + The type of an origin of the image. Options are: + + * `HTTP` — create an image from a file published on http/https service at a given url + * `ContainerImage` — create the image from image stored in container registry. + * `ObjectRef` — fill the disk from another existing resource. + * `Upload` — fill the image with data, uploaded by user via the special interface. + enum: + - HTTP + - ContainerImage + - ObjectRef + - Upload + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: HTTP requires http and cannot have ContainerImage or ObjectRef + rule: + "self.type == 'HTTP' ? has(self.http) && !has(self.containerImage) + && !has(self.objectRef) : true" + - message: + ContainerImage requires containerImage and cannot have + HTTP or ObjectRef + rule: + "self.type == 'ContainerImage' ? has(self.containerImage) + && !has(self.http) && !has(self.objectRef) : true" + - message: ObjectRef requires objectRef and cannot have HTTP or ContainerImage + rule: + "self.type == 'ObjectRef' ? has(self.objectRef) && !has(self.http) + && !has(self.containerImage) : true" + required: + - dataSource type: object + status: properties: + cdrom: + description: + Whether the image is a format that is supposed to be + mounted as a cdrom, such as iso and so on. + type: boolean conditions: - description: | - The latest available observations of an object's current state. + description: + The latest available observations of an object's current + state. items: description: - "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -252,12 +291,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -270,74 +304,49 @@ spec: type: object type: array downloadSpeed: - type: object - description: | - Image download speed from an external source. Appears only during the `Provisioning` phase. + description: + Image download speed from an external source. Appears + only during the `Provisioning` phase. properties: avg: - type: string + description: Average download speed. example: 1 Mbps - description: | - Average download speed. - current: type: string - example: 5 Mbps - description: | - Current download speed. avgBytes: - type: string + description: Average download speed in bytes per second. example: 1012345 - description: | - Average download speed in bytes per second. - currentBytes: type: string + current: + description: Current download speed. + example: 5 Mbps + type: string + currentBytes: + description: Current download speed in bytes per second. example: 5123456 - description: | - Current download speed in bytes per second. + type: string + type: object format: + description: Discovered format of the image. type: string - description: | - Discovered format of the image. - size: - type: object - description: | - Discovered sizes of the image. + imageUploadURLs: properties: - stored: - type: string - example: 199M - description: | - Image size in DVCR or in PVC in human-readable format. - storedBytes: - type: string - example: 199001234 - description: | - Image size in DVCR or in PVC in bytes. - unpacked: + external: + description: + Command to upload the image using `Ingress` from + outside the cluster. type: string - example: 1G - description: | - Unpacked image size in human-readable format. - unpackedBytes: + inCluster: + description: + Command to upload the image using `Service` within + the cluster. type: string - example: 1000000234 - description: | - Unpacked image size in bytes. - cdrom: - type: boolean - description: | - Whether the image is a format that is supposed to be mounted as a cdrom, such as iso and so on. - target: type: object - properties: - registryURL: - type: string - example: dvcr..svc/cvi/:latest - description: | - Created image in DVCR. + observedGeneration: + description: The generation last processed by the controller. + format: int64 + type: integer phase: - type: string - description: | + description: |- Current status of `ClusterVirtualImage` resource: * Pending - The resource has been created and is on a waiting queue. * Provisioning - The process of resource creation (copying/downloading/building the image) is in progress. @@ -346,65 +355,61 @@ spec: * Failed - There was a problem when creating a resource. * Terminating - The process of resource deletion is in progress. enum: - [ - "Pending", - "Provisioning", - "WaitForUserUpload", - "Ready", - "Failed", - "Terminating", - ] - progress: + - Pending + - Provisioning + - WaitForUserUpload + - Ready + - Failed + - Terminating type: string - description: | - Progress of copying an image from source to DVCR. Appears only during the `Provisioning' phase. - uploadCommand: + progress: + description: + Progress of copying an image from source to DVCR. Appears + only during the `Provisioning' phase. type: string - description: | - Deprecated. Use imageUploadURLs instead. - imageUploadURLs: - type: object + size: + description: Discovered sizes of the image. properties: - external: + stored: + description: Image size in human-readable format. + example: 199M type: string - description: | - Command to upload the image using `Ingress` from outside the cluster. - inCluster: + storedBytes: + description: Image size in bytes. + example: 199001234 + type: string + unpacked: + description: Unpacked image size in human-readable format. + example: 1G + type: string + unpackedBytes: + description: Unpacked image size in bytes. + example: 1000000234 type: string - description: | - Command to upload the image using `Service` within the cluster. + type: object sourceUID: + description: + The UID of the source (`VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk`) used when creating the cluster virtual image. type: string - description: | - The UID of the source (`VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`) used when creating the cluster virtual image. - observedGeneration: - type: integer - description: | - The generation last processed by the controller. - additionalPrinterColumns: - - name: Phase - type: string - jsonPath: .status.phase - - name: CDROM - type: boolean - jsonPath: .status.cdrom - - name: Progress - type: string - jsonPath: .status.progress - - name: StoredSize - type: string - jsonPath: .status.size.stored - priority: 1 - - name: UnpackedSize - type: string - jsonPath: .status.size.unpacked - priority: 1 - - name: Registry URL - jsonPath: .status.target.registryURL - type: string - priority: 1 - - name: Age - type: date - jsonPath: .metadata.creationTimestamp + target: + properties: + registryURL: + description: Created image in DVCR. + example: dvcr..svc/cvi/:latest + type: string + type: object + uploadCommand: + description: Deprecated. Use imageUploadURLs instead. + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: The name must be no longer than 128 characters. + rule: self.metadata.name.size() <= 128 + served: true + storage: true subresources: status: {} diff --git a/crds/virtualimages.yaml b/crds/virtualimages.yaml index 8207219f5..3bf6c1f8a 100644 --- a/crds/virtualimages.yaml +++ b/crds/virtualimages.yaml @@ -1,99 +1,151 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: virtualimages.virtualization.deckhouse.io + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 labels: heritage: deckhouse module: virtualization + name: virtualimages.virtualization.deckhouse.io spec: group: virtualization.deckhouse.io - scope: Namespaced names: categories: - - all - virtualization - plural: virtualimages - singular: virtualimage + - all kind: VirtualImage + listKind: VirtualImageList + plural: virtualimages shortNames: - vi - vis - preserveUnknownFields: false + singular: virtualimage + scope: Namespaced versions: - - name: v1alpha2 - served: true - storage: true + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .status.cdrom + name: CDROM + type: boolean + - jsonPath: .status.progress + name: Progress + type: string + - jsonPath: .status.size.stored + name: StoredSize + priority: 1 + type: string + - jsonPath: .status.size.unpacked + name: UnpackedSize + priority: 1 + type: string + - jsonPath: .status.target.registryURL + name: Registry URL + priority: 1 + type: string + - jsonPath: .status.target.persistentVolumeClaimName + name: TargetPVC + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 schema: openAPIV3Schema: - type: object - description: | + description: |- This resource describes a virtual disk image or installation image (iso) that can be used as a data source for new `VirtualDisks` or can be mounted in `Virtuals`. - > This resource cannot be modified once it has been created. A container image is created under the hood of this resource, which is stored in a dedicated deckhouse virtualization container registy (DVCR) or PVC, into which the data from the source is filled. - required: - - spec - x-kubernetes-validations: - - rule: "self.metadata.name.size() <= 128" - message: "The name must be no longer than 128 characters." properties: - spec: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: type: object - required: - - storage - - dataSource + spec: properties: - storage: - type: string - enum: - - "ContainerRegistry" - - "Kubernetes" - default: ContainerRegistry - description: | - Storage type to store the image for current virtualization setup. - - * `ContainerRegistry` — use a dedicated deckhouse virtualization container registry (DVCR). In this case, images will be downloaded and injected to a container, then pushed to a DVCR (shipped with the virtualization module). - * `Kubernetes` - use a Persistent Volume Claim (PVC). dataSource: - type: object - description: | - An origin of the image. - required: - - type properties: - type: - type: string - enum: - - "HTTP" - - "ContainerImage" - - "ObjectRef" - - "Upload" - description: | - The type of an origin of the image. Options are: - - * `HTTP` — fill the image with data from some external http/https url. - * `ContainerImage` — use an image, stored in container registry image. - * `ObjectRef` — fill the disk from another existing resource. - * `Upload` — fill the image with data, uploaded by user via the special interface. - http: + containerImage: + description: + Use an image stored in external container registry. + Only TLS enabled registries are supported. Use caBundle field + to provide custom CA chain if needed. + properties: + caBundle: + description: + The CA chain in base64 format to verify the container + registry. + example: YWFhCg== + format: byte + type: string + image: + description: The container registry address of an image. + example: registry.example.com/images/slackware:15 + pattern: ^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$ + type: string + imagePullSecret: + properties: + name: + description: + A name of the secret containing registry + credentials which must be located in the same namespace. + type: string + type: object + required: + - image type: object - description: | + http: + description: |- Fill the image with data from some external url. Supported schemas are: * http * https For https schema there is an option to skip TLS verification. - required: - - url properties: - url: + caBundle: + description: The CA chain in base64 format to verify the url. + example: YWFhCg== + format: byte type: string - example: "https://mirror.example.com/images/slackware-15.qcow.gz" - # https://regex101.com/r/2zx8as/1 - pattern: ^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$ - description: | + checksum: + description: + A checksum of the file, provided by the url, + to verify if it was downloaded correctly or wasn't changed. + The file should match all specified checksums. + properties: + md5: + example: f3b59bed9f91e32fac1210184fcff6f5 + maxLength: 32 + minLength: 32 + pattern: ^[0-9a-fA-F]{32}$ + type: string + sha256: + example: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5 + maxLength: 64 + minLength: 64 + pattern: ^[0-9a-fA-F]{64}$ + type: string + type: object + url: + description: |- The http url with an image. The following formats are supported: * qcow2 * vmdk @@ -103,113 +155,100 @@ spec: these formats can also be compressed with the following formats: * gz * xz - caBundle: + example: https://mirror.example.com/images/slackware-15.qcow.gz + pattern: ^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$ type: string - format: byte - description: The CA chain in base64 format to verify the url. - example: | - YWFhCg== - checksum: - type: object - description: | - A checksum of the file, provided by the url, to verify if it was downloaded correctly or wasn't changed. The file should match all specified checksums. - properties: - md5: - description: "" - type: string - pattern: ^[0-9a-fA-F]{32}$ - minLength: 32 - maxLength: 32 - example: f3b59bed9f91e32fac1210184fcff6f5 - sha256: - description: "" - type: string - pattern: ^[0-9a-fA-F]{64}$ - minLength: 64 - maxLength: 64 - example: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5 - containerImage: - type: object required: - - image - description: | - Use an image stored in external container regitry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed. - properties: - image: - type: string - example: "registry.example.com/images/slackware:15" - # https://regex101.com/r/NXfP8Y/1 - pattern: ^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$ - description: | - The container registry address of an image. - imagePullSecret: - type: object - properties: - name: - type: string - description: | - A name of the secret containing registry credentials which must be located in the same namespace. - caBundle: - type: string - format: byte - description: | - The CA chain in base64 format to verify the container registry. - example: | - YWFhCg== - objectRef: + - url type: object - description: | - Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk` to create an image. - required: ["kind", "name"] + objectRef: + description: + Use an existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk` to create an image. properties: kind: - type: string - description: A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. + description: + A kind of existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk`. enum: - - "ClusterVirtualImage" - - "VirtualImage" - - "VirtualDisk" + - ClusterVirtualImage + - VirtualImage + - VirtualDisk + type: string name: + description: + A name of existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk`. type: string - description: | - A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`. - oneOf: - - properties: - type: - enum: ["HTTP"] - http: {} - required: ["http"] - - properties: - type: - enum: ["ContainerImage"] - containerImage: {} - required: ["containerImage"] - - properties: - type: - enum: ["ObjectRef"] - objectRef: {} - required: ["objectRef"] - - properties: - type: - enum: ["Upload"] - status: + required: + - kind + - name + type: object + type: + description: |- + The type of an origin of the image. Options are: + + * `HTTP` — create an image from a file published on http/https service at a given url + * `ContainerImage` — create the image from image stored in container registry. + * `ObjectRef` — fill the disk from another existing resource. + * `Upload` — fill the image with data, uploaded by user via the special interface. + enum: + - HTTP + - ContainerImage + - ObjectRef + - Upload + type: string + type: object + x-kubernetes-validations: + - message: HTTP requires http and cannot have ContainerImage or ObjectRef + rule: + "self.type == 'HTTP' ? has(self.http) && !has(self.containerImage) + && !has(self.objectRef) : true" + - message: + ContainerImage requires containerImage and cannot have + HTTP or ObjectRef + rule: + "self.type == 'ContainerImage' ? has(self.containerImage) + && !has(self.http) && !has(self.objectRef) : true" + - message: ObjectRef requires objectRef and cannot have HTTP or ContainerImage + rule: + "self.type == 'ObjectRef' ? has(self.objectRef) && !has(self.http) + && !has(self.containerImage) : true" + persistentVolumeClaim: + properties: + storageClass: + type: string + type: object + storage: + default: ContainerRegistry + description: |- + Storage type to store the image for current virtualization setup. + + * `ContainerRegistry` — use a dedicated deckhouse virtualization container registry (DVCR). In this case, images will be downloaded and injected to a container, then pushed to a DVCR (shipped with the virtualization module). + * `Kubernetes` - use a Persistent Volume Claim (PVC). + enum: + - ContainerRegistry + - Kubernetes + type: string + required: + - dataSource + - storage type: object + status: properties: + cdrom: + description: + Whether the image is a format that is supposed to be + mounted as a cdrom, such as iso and so on. + type: boolean conditions: - description: | - The latest available observations of an object's current state. + description: + The latest available observations of an object's current + state. items: description: - "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -250,12 +289,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -268,157 +302,122 @@ spec: type: object type: array downloadSpeed: - type: object - description: | - Image download speed from an external source. Appears only during the `Provisioning' phase. + description: + Image download speed from an external source. Appears + only during the `Provisioning` phase. properties: avg: - type: string + description: Average download speed. example: 1 Mbps - description: | - Average download speed. - current: type: string - example: 5 Mbps - description: | - Current download speed. avgBytes: - type: string + description: Average download speed in bytes per second. example: 1012345 - description: | - Average download speed in bytes per second. - currentBytes: type: string + current: + description: Current download speed. + example: 5 Mbps + type: string + currentBytes: + description: Current download speed in bytes per second. example: 5123456 - description: | - Current download speed in bytes per second. + type: string + type: object format: + description: Discovered format of the image. type: string - description: | - Discovered format of the image. - size: - type: object - description: | - Discovered sizes of the image. + imageUploadURLs: properties: - stored: - type: string - example: 199M - description: | - Image size in DVCR in human-readable format. - storedBytes: - type: string - example: 199001234 - description: | - Image size in DVCR in bytes. - unpacked: + external: + description: + Command to upload the image using `Ingress` from + outside the cluster. type: string - example: 1G - description: | - Unpacked image size in human-readable format. - unpackedBytes: + inCluster: + description: + Command to upload the image using `Service` within + the cluster. type: string - example: 1000000234 - description: | - Unpacked image size in bytes. - cdrom: - type: boolean - description: | - Whether the image is a format that is supposed to be mounted as a cdrom, such as iso and so on. - target: type: object - properties: - registryURL: - type: string - example: dvcr..svc/vi//:latest - description: | - Created image in DVCR. - persistentVolumeClaimName: - type: string - description: | - Created PersistentVolumeClaim name for Kubernetes storage. + observedGeneration: + description: The generation last processed by the controller. + format: int64 + type: integer phase: - type: string - description: | - Current status of `VirtualImage` resource: - + description: |- + Current status of `ClusterVirtualImage` resource: * Pending - The resource has been created and is on a waiting queue. * Provisioning - The process of resource creation (copying/downloading/building the image) is in progress. * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. * Ready - The resource is created and ready to use. * Failed - There was a problem when creating a resource. - * PVCLost - The child PVC of the resource is missing. The resource cannot be used. * Terminating - The process of resource deletion is in progress. - + * PVCLost - The child PVC of the resource is missing. The resource cannot be used. enum: - [ - "Pending", - "Provisioning", - "WaitForUserUpload", - "Ready", - "Failed", - "PVCLost", - "Terminating", - ] - progress: + - Pending + - Provisioning + - WaitForUserUpload + - Ready + - Failed + - Terminating + - PVCLost type: string - description: | - Progress of copying an image from source to DVCR. - uploadCommand: + progress: + description: Progress of copying an image from source to DVCR. type: string - description: | - Deprecated. Use imageUploadURLs instead. - imageUploadURLs: - type: object + size: + description: Discovered sizes of the image. properties: - external: + stored: + description: Image size in human-readable format. + example: 199M type: string - description: | - Command to upload the image using `Ingress` from outside the cluster. - inCluster: + storedBytes: + description: Image size in bytes. + example: 199001234 type: string - description: | - Command to upload the image using `Service` within the cluster. + unpacked: + description: Unpacked image size in human-readable format. + example: 1G + type: string + unpackedBytes: + description: Unpacked image size in bytes. + example: 1000000234 + type: string + type: object sourceUID: + description: + The UID of the source (`VirtualImage`, `ClusterVirtualImage` + or `VirtualDisk`) used when creating the virtual image. type: string - description: | - The UID of the source (`VirtualImage`, `ClusterVirtualImage` or `VirtualDisk`) used when creating the virtual image. storageClassName: + description: + The name of the StorageClass used by the PersistentVolumeClaim + if `Kubernetes` storage type used. type: string - description: | - The name of the StorageClass used by the PersistentVolumeClaim if `Kubernetes` storage type used. - observedGeneration: - type: integer - description: | - The generation last processed by the controller. - additionalPrinterColumns: - - name: Phase - type: string - jsonPath: .status.phase - - name: CDROM - type: boolean - jsonPath: .status.cdrom - - name: Progress - type: string - jsonPath: .status.progress - - name: StoredSize - type: string - jsonPath: .status.size.stored - priority: 1 - - name: UnpackedSize - type: string - jsonPath: .status.size.unpacked - priority: 1 - - name: Registry URL - jsonPath: .status.target.registryURL - type: string - priority: 1 - - name: TargetPVC - jsonPath: .status.target.persistentVolumeClaimName - type: string - priority: 1 - - name: Age - type: date - jsonPath: .metadata.creationTimestamp + target: + properties: + persistentVolumeClaimName: + description: + Created PersistentVolumeClaim name for Kubernetes + storage. + type: string + registryURL: + description: Created image in DVCR. + example: dvcr..svc/vi//:latest + type: string + type: object + uploadCommand: + description: Deprecated. Use imageUploadURLs instead. + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: The name must be no longer than 128 characters. + rule: self.metadata.name.size() <= 128 + served: true + storage: true subresources: status: {} diff --git a/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go b/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go index 05e822c9b..745295117 100644 --- a/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go +++ b/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go @@ -16,36 +16,94 @@ limitations under the License. package datasource -import virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" +import ( + "k8s.io/apimachinery/pkg/types" + + virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" +) type CABundle struct { Type virtv2.DataSourceType HTTP *virtv2.DataSourceHTTP - ContainerImage *virtv2.DataSourceContainerRegistry + ContainerImage *ContainerRegistry +} + +type ContainerRegistry struct { + Image string + ImagePullSecret types.NamespacedName + CABundle []byte } func NewCABundleForCVMI(ds virtv2.ClusterVirtualImageDataSource) *CABundle { - return &CABundle{ - Type: ds.Type, - HTTP: ds.HTTP, - ContainerImage: ds.ContainerImage, + switch ds.Type { + case virtv2.DataSourceTypeHTTP: + return &CABundle{ + Type: ds.Type, + HTTP: ds.HTTP, + } + case virtv2.DataSourceTypeContainerImage: + return &CABundle{ + Type: ds.Type, + ContainerImage: &ContainerRegistry{ + Image: ds.ContainerImage.Image, + ImagePullSecret: types.NamespacedName{ + Name: ds.ContainerImage.ImagePullSecret.Name, + Namespace: ds.ContainerImage.ImagePullSecret.Namespace, + }, + CABundle: ds.ContainerImage.CABundle, + }, + } } + + return &CABundle{Type: ds.Type} } -func NewCABundleForVMI(ds virtv2.VirtualImageDataSource) *CABundle { - return &CABundle{ - Type: ds.Type, - HTTP: ds.HTTP, - ContainerImage: ds.ContainerImage, +func NewCABundleForVMI(namespace string, ds virtv2.VirtualImageDataSource) *CABundle { + switch ds.Type { + case virtv2.DataSourceTypeHTTP: + return &CABundle{ + Type: ds.Type, + HTTP: ds.HTTP, + } + case virtv2.DataSourceTypeContainerImage: + return &CABundle{ + Type: ds.Type, + ContainerImage: &ContainerRegistry{ + Image: ds.ContainerImage.Image, + ImagePullSecret: types.NamespacedName{ + Name: ds.ContainerImage.ImagePullSecret.Name, + Namespace: namespace, + }, + CABundle: ds.ContainerImage.CABundle, + }, + } } + + return &CABundle{Type: ds.Type} } -func NewCABundleForVMD(ds *virtv2.VirtualDiskDataSource) *CABundle { - return &CABundle{ - Type: ds.Type, - HTTP: ds.HTTP, - ContainerImage: ds.ContainerImage, +func NewCABundleForVMD(namespace string, ds *virtv2.VirtualDiskDataSource) *CABundle { + switch ds.Type { + case virtv2.DataSourceTypeHTTP: + return &CABundle{ + Type: ds.Type, + HTTP: ds.HTTP, + } + case virtv2.DataSourceTypeContainerImage: + return &CABundle{ + Type: ds.Type, + ContainerImage: &ContainerRegistry{ + Image: ds.ContainerImage.Image, + ImagePullSecret: types.NamespacedName{ + Name: ds.ContainerImage.ImagePullSecret.Name, + Namespace: namespace, + }, + CABundle: ds.ContainerImage.CABundle, + }, + } } + + return &CABundle{Type: ds.Type} } func (ds *CABundle) HasCABundle() bool { @@ -69,6 +127,6 @@ func (ds *CABundle) GetCABundle() string { return "" } -func (ds *CABundle) GetContainerImage() *virtv2.DataSourceContainerRegistry { +func (ds *CABundle) GetContainerImage() *ContainerRegistry { return ds.ContainerImage } diff --git a/images/virtualization-artifact/pkg/common/datasource/image_pull_secret.go b/images/virtualization-artifact/pkg/common/datasource/image_pull_secret.go index 1359bb04b..378de78bc 100644 --- a/images/virtualization-artifact/pkg/common/datasource/image_pull_secret.go +++ b/images/virtualization-artifact/pkg/common/datasource/image_pull_secret.go @@ -16,9 +16,7 @@ limitations under the License. package datasource -import virtv2alpha1 "github.com/deckhouse/virtualization/api/core/v1alpha2" - -func ShouldCopyImagePullSecret(ctrImg *virtv2alpha1.DataSourceContainerRegistry, targetNS string) bool { +func ShouldCopyImagePullSecret(ctrImg *ContainerRegistry, targetNS string) bool { if ctrImg == nil || ctrImg.ImagePullSecret.Name == "" { return false } diff --git a/images/virtualization-artifact/pkg/controller/cvi/internal/life_cycle.go b/images/virtualization-artifact/pkg/controller/cvi/internal/life_cycle.go index be0a6225c..d3c281ef5 100644 --- a/images/virtualization-artifact/pkg/controller/cvi/internal/life_cycle.go +++ b/images/virtualization-artifact/pkg/controller/cvi/internal/life_cycle.go @@ -74,9 +74,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, cvi *virtv2.ClusterVirtual if readyCondition.Status != metav1.ConditionTrue && h.sources.Changed(ctx, cvi) { cvi.Status = virtv2.ClusterVirtualImageStatus{ - ImageStatus: virtv2.ImageStatus{ - Phase: virtv2.ImagePending, - }, + Phase: virtv2.ImagePending, Conditions: cvi.Status.Conditions, ObservedGeneration: cvi.Status.ObservedGeneration, } diff --git a/images/virtualization-artifact/pkg/controller/cvi/internal/source/registry.go b/images/virtualization-artifact/pkg/controller/cvi/internal/source/registry.go index edc43a1be..7a069fc56 100644 --- a/images/virtualization-artifact/pkg/controller/cvi/internal/source/registry.go +++ b/images/virtualization-artifact/pkg/controller/cvi/internal/source/registry.go @@ -229,7 +229,15 @@ func (ds RegistryDataSource) Validate(ctx context.Context, cvi *virtv2.ClusterVi func (ds RegistryDataSource) getEnvSettings(cvi *virtv2.ClusterVirtualImage, supgen *supplements.Generator) *importer.Settings { var settings importer.Settings - importer.ApplyRegistrySourceSettings(&settings, cvi.Spec.DataSource.ContainerImage, supgen) + containerImage := &datasource.ContainerRegistry{ + Image: cvi.Spec.DataSource.ContainerImage.Image, + ImagePullSecret: types.NamespacedName{ + Name: cvi.Spec.DataSource.ContainerImage.ImagePullSecret.Name, + Namespace: cvi.Spec.DataSource.ContainerImage.ImagePullSecret.Namespace, + }, + CABundle: cvi.Spec.DataSource.ContainerImage.CABundle, + } + importer.ApplyRegistrySourceSettings(&settings, containerImage, supgen) importer.ApplyDVCRDestinationSettings( &settings, ds.dvcrSettings, diff --git a/images/virtualization-artifact/pkg/controller/importer/settings.go b/images/virtualization-artifact/pkg/controller/importer/settings.go index c49c6f484..bcedfdb40 100644 --- a/images/virtualization-artifact/pkg/controller/importer/settings.go +++ b/images/virtualization-artifact/pkg/controller/importer/settings.go @@ -18,6 +18,7 @@ package importer import ( "github.com/deckhouse/virtualization-controller/pkg/common" + "github.com/deckhouse/virtualization-controller/pkg/common/datasource" dsutil "github.com/deckhouse/virtualization-controller/pkg/common/datasource" cc "github.com/deckhouse/virtualization-controller/pkg/controller/common" "github.com/deckhouse/virtualization-controller/pkg/controller/supplements" @@ -90,7 +91,7 @@ func ApplyHTTPSourceSettings(podEnvVars *Settings, http *virtv2alpha1.DataSource } // ApplyRegistrySourceSettings updates importer Pod settings to use registry source. -func ApplyRegistrySourceSettings(podEnvVars *Settings, ctrImg *virtv2alpha1.DataSourceContainerRegistry, supGen *supplements.Generator) { +func ApplyRegistrySourceSettings(podEnvVars *Settings, ctrImg *datasource.ContainerRegistry, supGen *supplements.Generator) { podEnvVars.Source = cc.SourceRegistry podEnvVars.Endpoint = common.DockerRegistrySchemePrefix + ctrImg.Image diff --git a/images/virtualization-artifact/pkg/controller/supplements/ensure.go b/images/virtualization-artifact/pkg/controller/supplements/ensure.go index e09e6cd23..08f8e09fd 100644 --- a/images/virtualization-artifact/pkg/controller/supplements/ensure.go +++ b/images/virtualization-artifact/pkg/controller/supplements/ensure.go @@ -27,19 +27,19 @@ import ( cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/deckhouse/virtualization-controller/pkg/common/datasource" dvutil "github.com/deckhouse/virtualization-controller/pkg/common/datavolume" ingutil "github.com/deckhouse/virtualization-controller/pkg/common/ingress" podutil "github.com/deckhouse/virtualization-controller/pkg/common/pod" "github.com/deckhouse/virtualization-controller/pkg/controller/supplements/copier" "github.com/deckhouse/virtualization-controller/pkg/dvcr" "github.com/deckhouse/virtualization-controller/pkg/sdk/framework/helper" - virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" ) type DataSource interface { HasCABundle() bool GetCABundle() string - GetContainerImage() *virtv2.DataSourceContainerRegistry + GetContainerImage() *datasource.ContainerRegistry } // EnsureForPod make supplements for importer or uploader Pod: @@ -116,7 +116,7 @@ func ShouldCopyUploaderTLSSecret(dvcrSettings *dvcr.Settings, supGen *Generator) return dvcrSettings.UploaderIngressSettings.TLSSecretNamespace != supGen.Namespace } -func ShouldCopyImagePullSecret(ctrImg *virtv2.DataSourceContainerRegistry, targetNS string) bool { +func ShouldCopyImagePullSecret(ctrImg *datasource.ContainerRegistry, targetNS string) bool { if ctrImg == nil || ctrImg.ImagePullSecret.Name == "" { return false } diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/source/http.go b/images/virtualization-artifact/pkg/controller/vd/internal/source/http.go index 22747f780..e53a8252c 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/source/http.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/source/http.go @@ -117,7 +117,7 @@ func (ds HTTPDataSource) Sync(ctx context.Context, vd *virtv2.VirtualDisk) (reco vd.Status.Progress = "0%" envSettings := ds.getEnvSettings(vd, supgen) - err = ds.importerService.Start(ctx, envSettings, vd, supgen, datasource.NewCABundleForVMD(vd.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vd, supgen, datasource.NewCABundleForVMD(vd.GetNamespace(), vd.Spec.DataSource)) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/source/registry.go b/images/virtualization-artifact/pkg/controller/vd/internal/source/registry.go index 8a5811b07..31cbb8287 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/source/registry.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/source/registry.go @@ -123,7 +123,7 @@ func (ds RegistryDataSource) Sync(ctx context.Context, vd *virtv2.VirtualDisk) ( vd.Status.Progress = "0%" envSettings := ds.getEnvSettings(vd, supgen) - err = ds.importerService.Start(ctx, envSettings, vd, supgen, datasource.NewCABundleForVMD(vd.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vd, supgen, datasource.NewCABundleForVMD(vd.GetNamespace(), vd.Spec.DataSource)) switch { case err == nil: // OK. @@ -311,7 +311,7 @@ func (ds RegistryDataSource) Validate(ctx context.Context, vd *virtv2.VirtualDis if vd.Spec.DataSource.ContainerImage.ImagePullSecret.Name != "" { secretName := types.NamespacedName{ - Namespace: vd.Spec.DataSource.ContainerImage.ImagePullSecret.Namespace, + Namespace: vd.GetNamespace(), Name: vd.Spec.DataSource.ContainerImage.ImagePullSecret.Name, } secret, err := helper.FetchObject[*corev1.Secret](ctx, secretName, ds.client, &corev1.Secret{}) @@ -334,7 +334,14 @@ func (ds RegistryDataSource) Name() string { func (ds RegistryDataSource) getEnvSettings(vd *virtv2.VirtualDisk, supgen *supplements.Generator) *importer.Settings { var settings importer.Settings - importer.ApplyRegistrySourceSettings(&settings, vd.Spec.DataSource.ContainerImage, supgen) + containerImage := &datasource.ContainerRegistry{ + Image: vd.Spec.DataSource.ContainerImage.Image, + ImagePullSecret: types.NamespacedName{ + Name: vd.Spec.DataSource.ContainerImage.ImagePullSecret.Name, + Namespace: vd.GetNamespace(), + }, + } + importer.ApplyRegistrySourceSettings(&settings, containerImage, supgen) importer.ApplyDVCRDestinationSettings( &settings, ds.dvcrSettings, diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/source/upload.go b/images/virtualization-artifact/pkg/controller/vd/internal/source/upload.go index 163c4e22b..d0fb22c1b 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/source/upload.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/source/upload.go @@ -125,7 +125,7 @@ func (ds UploadDataSource) Sync(ctx context.Context, vd *virtv2.VirtualDisk) (re vd.Status.Progress = "0%" envSettings := ds.getEnvSettings(vd, supgen) - err = ds.uploaderService.Start(ctx, envSettings, vd, supgen, datasource.NewCABundleForVMD(vd.Spec.DataSource)) + err = ds.uploaderService.Start(ctx, envSettings, vd, supgen, datasource.NewCABundleForVMD(vd.GetNamespace(), vd.Spec.DataSource)) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/life_cycle.go b/images/virtualization-artifact/pkg/controller/vi/internal/life_cycle.go index 47bf43c97..9d813fe37 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/life_cycle.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/life_cycle.go @@ -73,9 +73,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vi *virtv2.VirtualImage) ( if readyCondition.Status != metav1.ConditionTrue && h.sources.Changed(ctx, vi) { vi.Status = virtv2.VirtualImageStatus{ - ImageStatus: virtv2.ImageStatus{ - Phase: virtv2.ImagePending, - }, + Phase: virtv2.ImagePending, Conditions: vi.Status.Conditions, ObservedGeneration: vi.Status.ObservedGeneration, } @@ -109,9 +107,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vi *virtv2.VirtualImage) ( storageClassReadyCondition.Status != metav1.ConditionTrue && vi.Status.StorageClassName != "" { vi.Status = virtv2.VirtualImageStatus{ - ImageStatus: virtv2.ImageStatus{ - Phase: virtv2.ImagePending, - }, + Phase: virtv2.ImagePending, Conditions: vi.Status.Conditions, ObservedGeneration: vi.Status.ObservedGeneration, StorageClassName: vi.Status.StorageClassName, diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/source/http.go b/images/virtualization-artifact/pkg/controller/vi/internal/source/http.go index 0851b055a..99ac3db89 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/source/http.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/source/http.go @@ -104,7 +104,7 @@ func (ds HTTPDataSource) StoreToDVCR(ctx context.Context, vi *virtv2.VirtualImag envSettings := ds.getEnvSettings(vi, supgen) - err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. @@ -233,7 +233,7 @@ func (ds HTTPDataSource) StoreToPVC(ctx context.Context, vi *virtv2.VirtualImage vi.Status.Progress = ds.statService.GetProgress(vi.GetUID(), pod, vi.Status.Progress) envSettings := ds.getEnvSettings(vi, supgen) - err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref.go b/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref.go index 078364b28..805315c4a 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref.go @@ -323,7 +323,7 @@ func (ds ObjectRefDataSource) StoreToDVCR(ctx context.Context, vi *virtv2.Virtua return reconcile.Result{}, err } - err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vd.go b/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vd.go index d7dbc0bbe..deedc6db0 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vd.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vd.go @@ -102,7 +102,7 @@ func (ds ObjectRefVirtualDisk) StoreToDVCR(ctx context.Context, vi *virtv2.Virtu ownerRef := metav1.NewControllerRef(vi, vi.GroupVersionKind()) podSettings := ds.importerService.GetPodSettingsWithPVC(ownerRef, supgen, vdRef.Status.Target.PersistentVolumeClaim, vdRef.Namespace) - err = ds.importerService.StartWithPodSetting(ctx, envSettings, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource), podSettings) + err = ds.importerService.StartWithPodSetting(ctx, envSettings, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource), podSettings) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vi_on_pvc.go b/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vi_on_pvc.go index 613ef0c23..16310deb7 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vi_on_pvc.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/source/object_ref_vi_on_pvc.go @@ -106,7 +106,7 @@ func (ds ObjectRefDataVirtualImageOnPVC) StoreToDVCR(ctx context.Context, vi, vi ownerRef := metav1.NewControllerRef(vi, vi.GroupVersionKind()) podSettings := ds.importerService.GetPodSettingsWithPVC(ownerRef, supgen, viRef.Status.Target.PersistentVolumeClaim, viRef.Namespace) - err = ds.importerService.StartWithPodSetting(ctx, envSettings, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource), podSettings) + err = ds.importerService.StartWithPodSetting(ctx, envSettings, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource), podSettings) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/source/registry.go b/images/virtualization-artifact/pkg/controller/vi/internal/source/registry.go index ee2ce46d7..a2b46c3b4 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/source/registry.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/source/registry.go @@ -126,7 +126,7 @@ func (ds RegistryDataSource) StoreToPVC(ctx context.Context, vi *virtv2.VirtualI vi.Status.Progress = "0%" envSettings := ds.getEnvSettings(vi, supgen) - err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. @@ -291,7 +291,7 @@ func (ds RegistryDataSource) StoreToDVCR(ctx context.Context, vi *virtv2.Virtual vi.Status.Progress = "0%" envSettings := ds.getEnvSettings(vi, supgen) - err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.importerService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. @@ -381,7 +381,7 @@ func (ds RegistryDataSource) CleanUp(ctx context.Context, vi *virtv2.VirtualImag func (ds RegistryDataSource) Validate(ctx context.Context, vi *virtv2.VirtualImage) error { if vi.Spec.DataSource.ContainerImage.ImagePullSecret.Name != "" { secretName := types.NamespacedName{ - Namespace: vi.Spec.DataSource.ContainerImage.ImagePullSecret.Namespace, + Namespace: vi.GetNamespace(), Name: vi.Spec.DataSource.ContainerImage.ImagePullSecret.Name, } secret, err := helper.FetchObject[*corev1.Secret](ctx, secretName, ds.client, &corev1.Secret{}) @@ -400,7 +400,15 @@ func (ds RegistryDataSource) Validate(ctx context.Context, vi *virtv2.VirtualIma func (ds RegistryDataSource) getEnvSettings(vi *virtv2.VirtualImage, supgen *supplements.Generator) *importer.Settings { var settings importer.Settings - importer.ApplyRegistrySourceSettings(&settings, vi.Spec.DataSource.ContainerImage, supgen) + containerImage := &datasource.ContainerRegistry{ + Image: vi.Spec.DataSource.ContainerImage.Image, + ImagePullSecret: types.NamespacedName{ + Name: vi.Spec.DataSource.ContainerImage.ImagePullSecret.Name, + Namespace: vi.GetNamespace(), + }, + CABundle: vi.Spec.DataSource.ContainerImage.CABundle, + } + importer.ApplyRegistrySourceSettings(&settings, containerImage, supgen) importer.ApplyDVCRDestinationSettings( &settings, ds.dvcrSettings, diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/source/upload.go b/images/virtualization-artifact/pkg/controller/vi/internal/source/upload.go index d7e2e62ee..4f89fa41f 100644 --- a/images/virtualization-artifact/pkg/controller/vi/internal/source/upload.go +++ b/images/virtualization-artifact/pkg/controller/vi/internal/source/upload.go @@ -128,7 +128,7 @@ func (ds UploadDataSource) StoreToPVC(ctx context.Context, vi *virtv2.VirtualIma vi.Status.Progress = "0%" envSettings := ds.getEnvSettings(vi, supgen) - err = ds.uploaderService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.uploaderService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. @@ -330,7 +330,7 @@ func (ds UploadDataSource) StoreToDVCR(ctx context.Context, vi *virtv2.VirtualIm log.Info("Cleaning up...") case pod == nil || svc == nil || ing == nil: envSettings := ds.getEnvSettings(vi, supgen) - err = ds.uploaderService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.Spec.DataSource)) + err = ds.uploaderService.Start(ctx, envSettings, vi, supgen, datasource.NewCABundleForVMI(vi.GetNamespace(), vi.Spec.DataSource)) switch { case err == nil: // OK. diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/block_devices_test.go b/images/virtualization-artifact/pkg/controller/vm/internal/block_devices_test.go index 6c88718ee..78d9d1aa7 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/block_devices_test.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/block_devices_test.go @@ -57,15 +57,11 @@ var _ = Describe("BlockDeviceHandler", func() { }) vi = &virtv2.VirtualImage{ ObjectMeta: metav1.ObjectMeta{Name: "vi-01"}, - Status: virtv2.VirtualImageStatus{ - ImageStatus: virtv2.ImageStatus{Phase: virtv2.ImageReady}, - }, + Status: virtv2.VirtualImageStatus{Phase: virtv2.ImageReady}, } cvi = &virtv2.ClusterVirtualImage{ ObjectMeta: metav1.ObjectMeta{Name: "cvi-01"}, - Status: virtv2.ClusterVirtualImageStatus{ - ImageStatus: virtv2.ImageStatus{Phase: virtv2.ImageReady}, - }, + Status: virtv2.ClusterVirtualImageStatus{Phase: virtv2.ImageReady}, } vdFoo = &virtv2.VirtualDisk{ ObjectMeta: metav1.ObjectMeta{Name: "vd-foo"},