diff --git a/api/client/examples/list-resources/go.mod b/api/client/examples/list-resources/go.mod index f8d10a8e2..84c84e1c4 100644 --- a/api/client/examples/list-resources/go.mod +++ b/api/client/examples/list-resources/go.mod @@ -3,13 +3,13 @@ module github.com/deckhouse/virtualization/api/client/examples/list-resources go 1.21.4 require ( + github.com/deckhouse/virtualization/api v0.0.0-20240322104947-2d492906a8b2 github.com/spf13/pflag v1.0.5 k8s.io/apimachinery v0.29.3 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckhouse/virtualization/api v0.0.0-20240322104947-2d492906a8b2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -24,7 +24,6 @@ require ( github.com/imdario/mergo v0.3.6 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -40,7 +39,6 @@ require ( golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -57,3 +55,5 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) + +replace github.com/deckhouse/virtualization/api => ./../../../../api diff --git a/api/client/examples/list-resources/go.sum b/api/client/examples/list-resources/go.sum index d104128f9..41bc2895b 100644 --- a/api/client/examples/list-resources/go.sum +++ b/api/client/examples/list-resources/go.sum @@ -13,8 +13,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckhouse/virtualization/api v0.0.0-20240322104947-2d492906a8b2 h1:MAd0jTNLaRjtJCFzz4j3UMkb+Tder8tFQufR24EXq2o= -github.com/deckhouse/virtualization/api v0.0.0-20240322104947-2d492906a8b2/go.mod h1:1tfoFeZmlKqq6jEuSfIpdrxsBpOcMajYaCbO94pVQLs= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -51,6 +49,8 @@ github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/e github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -84,6 +84,8 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -138,13 +140,18 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 h1:t/CahSnpqY46sQR01SoS+Jt0jtjgmhgE6lFmRnO4q70= github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= @@ -271,6 +278,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/api/client/examples/list-resources/main.go b/api/client/examples/list-resources/main.go index bea58345a..f10471955 100644 --- a/api/client/examples/list-resources/main.go +++ b/api/client/examples/list-resources/main.go @@ -3,12 +3,14 @@ package main import ( "context" "fmt" - kubeclient "github.com/deckhouse/virtualization/api/client/kubeclient" - "github.com/spf13/pflag" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "log" "os" "text/tabwriter" + + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/deckhouse/virtualization/api/client/kubeclient" ) func main() { @@ -35,17 +37,17 @@ func main() { log.Fatalf("Cannot fetch VirtualMachines in namespace %s: %v", namespace, err) } // Fetch list of Disks. - diskList, err := client.VirtualMachineDisks(namespace).List(context.TODO(), metav1.ListOptions{}) + diskList, err := client.VirtualDisks(namespace).List(context.TODO(), metav1.ListOptions{}) if err != nil { log.Fatalf("Cannot fetch Disks in namespace %s: %v", namespace, err) } // Fetch list of Images. - imgList, err := client.VirtualMachineImages(namespace).List(context.TODO(), metav1.ListOptions{}) + imgList, err := client.VirtualImages(namespace).List(context.TODO(), metav1.ListOptions{}) if err != nil { log.Fatalf("Cannot fetch Images in namespace %s: %v", namespace, err) } // Fetch list of ClusterImages. - cimgList, err := client.ClusterVirtualMachineImages().List(context.TODO(), metav1.ListOptions{}) + cimgList, err := client.ClusterVirtualImages().List(context.TODO(), metav1.ListOptions{}) if err != nil { log.Fatalf("Cannot fetch ClusterImages: %v", err) } diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/clustervirtualimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/clustervirtualimage.go new file mode 100644 index 000000000..992e0aa75 --- /dev/null +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/clustervirtualimage.go @@ -0,0 +1,183 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "context" + "time" + + scheme "github.com/deckhouse/virtualization/api/client/generated/clientset/versioned/scheme" + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ClusterVirtualImagesGetter has a method to return a ClusterVirtualImageInterface. +// A group's client should implement this interface. +type ClusterVirtualImagesGetter interface { + ClusterVirtualImages() ClusterVirtualImageInterface +} + +// ClusterVirtualImageInterface has methods to work with ClusterVirtualImage resources. +type ClusterVirtualImageInterface interface { + Create(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.CreateOptions) (*v1alpha2.ClusterVirtualImage, error) + Update(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.UpdateOptions) (*v1alpha2.ClusterVirtualImage, error) + UpdateStatus(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.UpdateOptions) (*v1alpha2.ClusterVirtualImage, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.ClusterVirtualImage, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.ClusterVirtualImageList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ClusterVirtualImage, err error) + ClusterVirtualImageExpansion +} + +// clusterVirtualImages implements ClusterVirtualImageInterface +type clusterVirtualImages struct { + client rest.Interface +} + +// newClusterVirtualImages returns a ClusterVirtualImages +func newClusterVirtualImages(c *VirtualizationV1alpha2Client) *clusterVirtualImages { + return &clusterVirtualImages{ + client: c.RESTClient(), + } +} + +// Get takes name of the clusterVirtualImage, and returns the corresponding clusterVirtualImage object, and an error if there is any. +func (c *clusterVirtualImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + result = &v1alpha2.ClusterVirtualImage{} + err = c.client.Get(). + Resource("clustervirtualimages"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ClusterVirtualImages that match those selectors. +func (c *clusterVirtualImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ClusterVirtualImageList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha2.ClusterVirtualImageList{} + err = c.client.Get(). + Resource("clustervirtualimages"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested clusterVirtualImages. +func (c *clusterVirtualImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("clustervirtualimages"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a clusterVirtualImage and creates it. Returns the server's representation of the clusterVirtualImage, and an error, if there is any. +func (c *clusterVirtualImages) Create(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.CreateOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + result = &v1alpha2.ClusterVirtualImage{} + err = c.client.Post(). + Resource("clustervirtualimages"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterVirtualImage). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a clusterVirtualImage and updates it. Returns the server's representation of the clusterVirtualImage, and an error, if there is any. +func (c *clusterVirtualImages) Update(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.UpdateOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + result = &v1alpha2.ClusterVirtualImage{} + err = c.client.Put(). + Resource("clustervirtualimages"). + Name(clusterVirtualImage.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterVirtualImage). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *clusterVirtualImages) UpdateStatus(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.UpdateOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + result = &v1alpha2.ClusterVirtualImage{} + err = c.client.Put(). + Resource("clustervirtualimages"). + Name(clusterVirtualImage.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterVirtualImage). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the clusterVirtualImage and deletes it. Returns an error if one occurs. +func (c *clusterVirtualImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("clustervirtualimages"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *clusterVirtualImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("clustervirtualimages"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched clusterVirtualImage. +func (c *clusterVirtualImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ClusterVirtualImage, err error) { + result = &v1alpha2.ClusterVirtualImage{} + err = c.client.Patch(pt). + Resource("clustervirtualimages"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/clustervirtualmachineimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/clustervirtualmachineimage.go deleted file mode 100644 index 85fd0353d..000000000 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/clustervirtualmachineimage.go +++ /dev/null @@ -1,183 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha2 - -import ( - "context" - "time" - - scheme "github.com/deckhouse/virtualization/api/client/generated/clientset/versioned/scheme" - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// ClusterVirtualMachineImagesGetter has a method to return a ClusterVirtualMachineImageInterface. -// A group's client should implement this interface. -type ClusterVirtualMachineImagesGetter interface { - ClusterVirtualMachineImages() ClusterVirtualMachineImageInterface -} - -// ClusterVirtualMachineImageInterface has methods to work with ClusterVirtualMachineImage resources. -type ClusterVirtualMachineImageInterface interface { - Create(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.CreateOptions) (*v1alpha2.ClusterVirtualMachineImage, error) - Update(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.UpdateOptions) (*v1alpha2.ClusterVirtualMachineImage, error) - UpdateStatus(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.UpdateOptions) (*v1alpha2.ClusterVirtualMachineImage, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.ClusterVirtualMachineImage, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.ClusterVirtualMachineImageList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ClusterVirtualMachineImage, err error) - ClusterVirtualMachineImageExpansion -} - -// clusterVirtualMachineImages implements ClusterVirtualMachineImageInterface -type clusterVirtualMachineImages struct { - client rest.Interface -} - -// newClusterVirtualMachineImages returns a ClusterVirtualMachineImages -func newClusterVirtualMachineImages(c *VirtualizationV1alpha2Client) *clusterVirtualMachineImages { - return &clusterVirtualMachineImages{ - client: c.RESTClient(), - } -} - -// Get takes name of the clusterVirtualMachineImage, and returns the corresponding clusterVirtualMachineImage object, and an error if there is any. -func (c *clusterVirtualMachineImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - result = &v1alpha2.ClusterVirtualMachineImage{} - err = c.client.Get(). - Resource("clustervirtualmachineimages"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ClusterVirtualMachineImages that match those selectors. -func (c *clusterVirtualMachineImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ClusterVirtualMachineImageList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha2.ClusterVirtualMachineImageList{} - err = c.client.Get(). - Resource("clustervirtualmachineimages"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested clusterVirtualMachineImages. -func (c *clusterVirtualMachineImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Resource("clustervirtualmachineimages"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a clusterVirtualMachineImage and creates it. Returns the server's representation of the clusterVirtualMachineImage, and an error, if there is any. -func (c *clusterVirtualMachineImages) Create(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.CreateOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - result = &v1alpha2.ClusterVirtualMachineImage{} - err = c.client.Post(). - Resource("clustervirtualmachineimages"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterVirtualMachineImage). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a clusterVirtualMachineImage and updates it. Returns the server's representation of the clusterVirtualMachineImage, and an error, if there is any. -func (c *clusterVirtualMachineImages) Update(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.UpdateOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - result = &v1alpha2.ClusterVirtualMachineImage{} - err = c.client.Put(). - Resource("clustervirtualmachineimages"). - Name(clusterVirtualMachineImage.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterVirtualMachineImage). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *clusterVirtualMachineImages) UpdateStatus(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.UpdateOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - result = &v1alpha2.ClusterVirtualMachineImage{} - err = c.client.Put(). - Resource("clustervirtualmachineimages"). - Name(clusterVirtualMachineImage.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterVirtualMachineImage). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the clusterVirtualMachineImage and deletes it. Returns an error if one occurs. -func (c *clusterVirtualMachineImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Resource("clustervirtualmachineimages"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *clusterVirtualMachineImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Resource("clustervirtualmachineimages"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched clusterVirtualMachineImage. -func (c *clusterVirtualMachineImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - result = &v1alpha2.ClusterVirtualMachineImage{} - err = c.client.Patch(pt). - Resource("clustervirtualmachineimages"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/core_client.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/core_client.go index 97070a2d6..982cbaa08 100644 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/core_client.go +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/core_client.go @@ -27,14 +27,14 @@ import ( type VirtualizationV1alpha2Interface interface { RESTClient() rest.Interface - ClusterVirtualMachineImagesGetter + ClusterVirtualImagesGetter + VirtualDisksGetter + VirtualImagesGetter VirtualMachinesGetter VirtualMachineBlockDeviceAttachmentsGetter VirtualMachineCPUModelsGetter - VirtualMachineDisksGetter VirtualMachineIPAddressClaimsGetter VirtualMachineIPAddressLeasesGetter - VirtualMachineImagesGetter VirtualMachineOperationsGetter } @@ -43,8 +43,16 @@ type VirtualizationV1alpha2Client struct { restClient rest.Interface } -func (c *VirtualizationV1alpha2Client) ClusterVirtualMachineImages() ClusterVirtualMachineImageInterface { - return newClusterVirtualMachineImages(c) +func (c *VirtualizationV1alpha2Client) ClusterVirtualImages() ClusterVirtualImageInterface { + return newClusterVirtualImages(c) +} + +func (c *VirtualizationV1alpha2Client) VirtualDisks(namespace string) VirtualDiskInterface { + return newVirtualDisks(c, namespace) +} + +func (c *VirtualizationV1alpha2Client) VirtualImages(namespace string) VirtualImageInterface { + return newVirtualImages(c, namespace) } func (c *VirtualizationV1alpha2Client) VirtualMachines(namespace string) VirtualMachineInterface { @@ -59,10 +67,6 @@ func (c *VirtualizationV1alpha2Client) VirtualMachineCPUModels() VirtualMachineC return newVirtualMachineCPUModels(c) } -func (c *VirtualizationV1alpha2Client) VirtualMachineDisks(namespace string) VirtualMachineDiskInterface { - return newVirtualMachineDisks(c, namespace) -} - func (c *VirtualizationV1alpha2Client) VirtualMachineIPAddressClaims(namespace string) VirtualMachineIPAddressClaimInterface { return newVirtualMachineIPAddressClaims(c, namespace) } @@ -71,10 +75,6 @@ func (c *VirtualizationV1alpha2Client) VirtualMachineIPAddressLeases() VirtualMa return newVirtualMachineIPAddressLeases(c) } -func (c *VirtualizationV1alpha2Client) VirtualMachineImages(namespace string) VirtualMachineImageInterface { - return newVirtualMachineImages(c, namespace) -} - func (c *VirtualizationV1alpha2Client) VirtualMachineOperations(namespace string) VirtualMachineOperationInterface { return newVirtualMachineOperations(c, namespace) } diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_clustervirtualimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_clustervirtualimage.go new file mode 100644 index 000000000..d337e1b3b --- /dev/null +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_clustervirtualimage.go @@ -0,0 +1,131 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeClusterVirtualImages implements ClusterVirtualImageInterface +type FakeClusterVirtualImages struct { + Fake *FakeVirtualizationV1alpha2 +} + +var clustervirtualimagesResource = v1alpha2.SchemeGroupVersion.WithResource("clustervirtualimages") + +var clustervirtualimagesKind = v1alpha2.SchemeGroupVersion.WithKind("ClusterVirtualImage") + +// Get takes name of the clusterVirtualImage, and returns the corresponding clusterVirtualImage object, and an error if there is any. +func (c *FakeClusterVirtualImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(clustervirtualimagesResource, name), &v1alpha2.ClusterVirtualImage{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ClusterVirtualImage), err +} + +// List takes label and field selectors, and returns the list of ClusterVirtualImages that match those selectors. +func (c *FakeClusterVirtualImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ClusterVirtualImageList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(clustervirtualimagesResource, clustervirtualimagesKind, opts), &v1alpha2.ClusterVirtualImageList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.ClusterVirtualImageList{ListMeta: obj.(*v1alpha2.ClusterVirtualImageList).ListMeta} + for _, item := range obj.(*v1alpha2.ClusterVirtualImageList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested clusterVirtualImages. +func (c *FakeClusterVirtualImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(clustervirtualimagesResource, opts)) +} + +// Create takes the representation of a clusterVirtualImage and creates it. Returns the server's representation of the clusterVirtualImage, and an error, if there is any. +func (c *FakeClusterVirtualImages) Create(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.CreateOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(clustervirtualimagesResource, clusterVirtualImage), &v1alpha2.ClusterVirtualImage{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ClusterVirtualImage), err +} + +// Update takes the representation of a clusterVirtualImage and updates it. Returns the server's representation of the clusterVirtualImage, and an error, if there is any. +func (c *FakeClusterVirtualImages) Update(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.UpdateOptions) (result *v1alpha2.ClusterVirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(clustervirtualimagesResource, clusterVirtualImage), &v1alpha2.ClusterVirtualImage{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ClusterVirtualImage), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeClusterVirtualImages) UpdateStatus(ctx context.Context, clusterVirtualImage *v1alpha2.ClusterVirtualImage, opts v1.UpdateOptions) (*v1alpha2.ClusterVirtualImage, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(clustervirtualimagesResource, "status", clusterVirtualImage), &v1alpha2.ClusterVirtualImage{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ClusterVirtualImage), err +} + +// Delete takes name of the clusterVirtualImage and deletes it. Returns an error if one occurs. +func (c *FakeClusterVirtualImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(clustervirtualimagesResource, name, opts), &v1alpha2.ClusterVirtualImage{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeClusterVirtualImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(clustervirtualimagesResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha2.ClusterVirtualImageList{}) + return err +} + +// Patch applies the patch and returns the patched clusterVirtualImage. +func (c *FakeClusterVirtualImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ClusterVirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(clustervirtualimagesResource, name, pt, data, subresources...), &v1alpha2.ClusterVirtualImage{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.ClusterVirtualImage), err +} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_clustervirtualmachineimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_clustervirtualmachineimage.go deleted file mode 100644 index 2d8075e36..000000000 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_clustervirtualmachineimage.go +++ /dev/null @@ -1,131 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeClusterVirtualMachineImages implements ClusterVirtualMachineImageInterface -type FakeClusterVirtualMachineImages struct { - Fake *FakeVirtualizationV1alpha2 -} - -var clustervirtualmachineimagesResource = v1alpha2.SchemeGroupVersion.WithResource("clustervirtualmachineimages") - -var clustervirtualmachineimagesKind = v1alpha2.SchemeGroupVersion.WithKind("ClusterVirtualMachineImage") - -// Get takes name of the clusterVirtualMachineImage, and returns the corresponding clusterVirtualMachineImage object, and an error if there is any. -func (c *FakeClusterVirtualMachineImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootGetAction(clustervirtualmachineimagesResource, name), &v1alpha2.ClusterVirtualMachineImage{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ClusterVirtualMachineImage), err -} - -// List takes label and field selectors, and returns the list of ClusterVirtualMachineImages that match those selectors. -func (c *FakeClusterVirtualMachineImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.ClusterVirtualMachineImageList, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootListAction(clustervirtualmachineimagesResource, clustervirtualmachineimagesKind, opts), &v1alpha2.ClusterVirtualMachineImageList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha2.ClusterVirtualMachineImageList{ListMeta: obj.(*v1alpha2.ClusterVirtualMachineImageList).ListMeta} - for _, item := range obj.(*v1alpha2.ClusterVirtualMachineImageList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested clusterVirtualMachineImages. -func (c *FakeClusterVirtualMachineImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewRootWatchAction(clustervirtualmachineimagesResource, opts)) -} - -// Create takes the representation of a clusterVirtualMachineImage and creates it. Returns the server's representation of the clusterVirtualMachineImage, and an error, if there is any. -func (c *FakeClusterVirtualMachineImages) Create(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.CreateOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootCreateAction(clustervirtualmachineimagesResource, clusterVirtualMachineImage), &v1alpha2.ClusterVirtualMachineImage{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ClusterVirtualMachineImage), err -} - -// Update takes the representation of a clusterVirtualMachineImage and updates it. Returns the server's representation of the clusterVirtualMachineImage, and an error, if there is any. -func (c *FakeClusterVirtualMachineImages) Update(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.UpdateOptions) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateAction(clustervirtualmachineimagesResource, clusterVirtualMachineImage), &v1alpha2.ClusterVirtualMachineImage{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ClusterVirtualMachineImage), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeClusterVirtualMachineImages) UpdateStatus(ctx context.Context, clusterVirtualMachineImage *v1alpha2.ClusterVirtualMachineImage, opts v1.UpdateOptions) (*v1alpha2.ClusterVirtualMachineImage, error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateSubresourceAction(clustervirtualmachineimagesResource, "status", clusterVirtualMachineImage), &v1alpha2.ClusterVirtualMachineImage{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ClusterVirtualMachineImage), err -} - -// Delete takes name of the clusterVirtualMachineImage and deletes it. Returns an error if one occurs. -func (c *FakeClusterVirtualMachineImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewRootDeleteActionWithOptions(clustervirtualmachineimagesResource, name, opts), &v1alpha2.ClusterVirtualMachineImage{}) - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeClusterVirtualMachineImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(clustervirtualmachineimagesResource, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha2.ClusterVirtualMachineImageList{}) - return err -} - -// Patch applies the patch and returns the patched clusterVirtualMachineImage. -func (c *FakeClusterVirtualMachineImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.ClusterVirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clustervirtualmachineimagesResource, name, pt, data, subresources...), &v1alpha2.ClusterVirtualMachineImage{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.ClusterVirtualMachineImage), err -} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_core_client.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_core_client.go index 67abe26d4..09d0259b4 100644 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_core_client.go +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_core_client.go @@ -27,8 +27,16 @@ type FakeVirtualizationV1alpha2 struct { *testing.Fake } -func (c *FakeVirtualizationV1alpha2) ClusterVirtualMachineImages() v1alpha2.ClusterVirtualMachineImageInterface { - return &FakeClusterVirtualMachineImages{c} +func (c *FakeVirtualizationV1alpha2) ClusterVirtualImages() v1alpha2.ClusterVirtualImageInterface { + return &FakeClusterVirtualImages{c} +} + +func (c *FakeVirtualizationV1alpha2) VirtualDisks(namespace string) v1alpha2.VirtualDiskInterface { + return &FakeVirtualDisks{c, namespace} +} + +func (c *FakeVirtualizationV1alpha2) VirtualImages(namespace string) v1alpha2.VirtualImageInterface { + return &FakeVirtualImages{c, namespace} } func (c *FakeVirtualizationV1alpha2) VirtualMachines(namespace string) v1alpha2.VirtualMachineInterface { @@ -43,10 +51,6 @@ func (c *FakeVirtualizationV1alpha2) VirtualMachineCPUModels() v1alpha2.VirtualM return &FakeVirtualMachineCPUModels{c} } -func (c *FakeVirtualizationV1alpha2) VirtualMachineDisks(namespace string) v1alpha2.VirtualMachineDiskInterface { - return &FakeVirtualMachineDisks{c, namespace} -} - func (c *FakeVirtualizationV1alpha2) VirtualMachineIPAddressClaims(namespace string) v1alpha2.VirtualMachineIPAddressClaimInterface { return &FakeVirtualMachineIPAddressClaims{c, namespace} } @@ -55,10 +59,6 @@ func (c *FakeVirtualizationV1alpha2) VirtualMachineIPAddressLeases() v1alpha2.Vi return &FakeVirtualMachineIPAddressLeases{c} } -func (c *FakeVirtualizationV1alpha2) VirtualMachineImages(namespace string) v1alpha2.VirtualMachineImageInterface { - return &FakeVirtualMachineImages{c, namespace} -} - func (c *FakeVirtualizationV1alpha2) VirtualMachineOperations(namespace string) v1alpha2.VirtualMachineOperationInterface { return &FakeVirtualMachineOperations{c, namespace} } diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualdisk.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualdisk.go new file mode 100644 index 000000000..6b5dc66b1 --- /dev/null +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualdisk.go @@ -0,0 +1,140 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVirtualDisks implements VirtualDiskInterface +type FakeVirtualDisks struct { + Fake *FakeVirtualizationV1alpha2 + ns string +} + +var virtualdisksResource = v1alpha2.SchemeGroupVersion.WithResource("virtualdisks") + +var virtualdisksKind = v1alpha2.SchemeGroupVersion.WithKind("VirtualDisk") + +// Get takes name of the virtualDisk, and returns the corresponding virtualDisk object, and an error if there is any. +func (c *FakeVirtualDisks) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualDisk, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(virtualdisksResource, c.ns, name), &v1alpha2.VirtualDisk{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualDisk), err +} + +// List takes label and field selectors, and returns the list of VirtualDisks that match those selectors. +func (c *FakeVirtualDisks) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualDiskList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(virtualdisksResource, virtualdisksKind, c.ns, opts), &v1alpha2.VirtualDiskList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.VirtualDiskList{ListMeta: obj.(*v1alpha2.VirtualDiskList).ListMeta} + for _, item := range obj.(*v1alpha2.VirtualDiskList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested virtualDisks. +func (c *FakeVirtualDisks) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(virtualdisksResource, c.ns, opts)) + +} + +// Create takes the representation of a virtualDisk and creates it. Returns the server's representation of the virtualDisk, and an error, if there is any. +func (c *FakeVirtualDisks) Create(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.CreateOptions) (result *v1alpha2.VirtualDisk, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(virtualdisksResource, c.ns, virtualDisk), &v1alpha2.VirtualDisk{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualDisk), err +} + +// Update takes the representation of a virtualDisk and updates it. Returns the server's representation of the virtualDisk, and an error, if there is any. +func (c *FakeVirtualDisks) Update(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.UpdateOptions) (result *v1alpha2.VirtualDisk, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(virtualdisksResource, c.ns, virtualDisk), &v1alpha2.VirtualDisk{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualDisk), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeVirtualDisks) UpdateStatus(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.UpdateOptions) (*v1alpha2.VirtualDisk, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(virtualdisksResource, "status", c.ns, virtualDisk), &v1alpha2.VirtualDisk{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualDisk), err +} + +// Delete takes name of the virtualDisk and deletes it. Returns an error if one occurs. +func (c *FakeVirtualDisks) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(virtualdisksResource, c.ns, name, opts), &v1alpha2.VirtualDisk{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVirtualDisks) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(virtualdisksResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha2.VirtualDiskList{}) + return err +} + +// Patch applies the patch and returns the patched virtualDisk. +func (c *FakeVirtualDisks) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualDisk, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(virtualdisksResource, c.ns, name, pt, data, subresources...), &v1alpha2.VirtualDisk{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualDisk), err +} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualimage.go new file mode 100644 index 000000000..dcf0b64ba --- /dev/null +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualimage.go @@ -0,0 +1,140 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVirtualImages implements VirtualImageInterface +type FakeVirtualImages struct { + Fake *FakeVirtualizationV1alpha2 + ns string +} + +var virtualimagesResource = v1alpha2.SchemeGroupVersion.WithResource("virtualimages") + +var virtualimagesKind = v1alpha2.SchemeGroupVersion.WithKind("VirtualImage") + +// Get takes name of the virtualImage, and returns the corresponding virtualImage object, and an error if there is any. +func (c *FakeVirtualImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(virtualimagesResource, c.ns, name), &v1alpha2.VirtualImage{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualImage), err +} + +// List takes label and field selectors, and returns the list of VirtualImages that match those selectors. +func (c *FakeVirtualImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualImageList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(virtualimagesResource, virtualimagesKind, c.ns, opts), &v1alpha2.VirtualImageList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.VirtualImageList{ListMeta: obj.(*v1alpha2.VirtualImageList).ListMeta} + for _, item := range obj.(*v1alpha2.VirtualImageList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested virtualImages. +func (c *FakeVirtualImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(virtualimagesResource, c.ns, opts)) + +} + +// Create takes the representation of a virtualImage and creates it. Returns the server's representation of the virtualImage, and an error, if there is any. +func (c *FakeVirtualImages) Create(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.CreateOptions) (result *v1alpha2.VirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(virtualimagesResource, c.ns, virtualImage), &v1alpha2.VirtualImage{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualImage), err +} + +// Update takes the representation of a virtualImage and updates it. Returns the server's representation of the virtualImage, and an error, if there is any. +func (c *FakeVirtualImages) Update(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.UpdateOptions) (result *v1alpha2.VirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(virtualimagesResource, c.ns, virtualImage), &v1alpha2.VirtualImage{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualImage), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeVirtualImages) UpdateStatus(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.UpdateOptions) (*v1alpha2.VirtualImage, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(virtualimagesResource, "status", c.ns, virtualImage), &v1alpha2.VirtualImage{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualImage), err +} + +// Delete takes name of the virtualImage and deletes it. Returns an error if one occurs. +func (c *FakeVirtualImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(virtualimagesResource, c.ns, name, opts), &v1alpha2.VirtualImage{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVirtualImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(virtualimagesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha2.VirtualImageList{}) + return err +} + +// Patch applies the patch and returns the patched virtualImage. +func (c *FakeVirtualImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualImage, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(virtualimagesResource, c.ns, name, pt, data, subresources...), &v1alpha2.VirtualImage{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.VirtualImage), err +} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualmachinedisk.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualmachinedisk.go deleted file mode 100644 index b5a47e063..000000000 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualmachinedisk.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeVirtualMachineDisks implements VirtualMachineDiskInterface -type FakeVirtualMachineDisks struct { - Fake *FakeVirtualizationV1alpha2 - ns string -} - -var virtualmachinedisksResource = v1alpha2.SchemeGroupVersion.WithResource("virtualmachinedisks") - -var virtualmachinedisksKind = v1alpha2.SchemeGroupVersion.WithKind("VirtualMachineDisk") - -// Get takes name of the virtualMachineDisk, and returns the corresponding virtualMachineDisk object, and an error if there is any. -func (c *FakeVirtualMachineDisks) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(virtualmachinedisksResource, c.ns, name), &v1alpha2.VirtualMachineDisk{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineDisk), err -} - -// List takes label and field selectors, and returns the list of VirtualMachineDisks that match those selectors. -func (c *FakeVirtualMachineDisks) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualMachineDiskList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(virtualmachinedisksResource, virtualmachinedisksKind, c.ns, opts), &v1alpha2.VirtualMachineDiskList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha2.VirtualMachineDiskList{ListMeta: obj.(*v1alpha2.VirtualMachineDiskList).ListMeta} - for _, item := range obj.(*v1alpha2.VirtualMachineDiskList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested virtualMachineDisks. -func (c *FakeVirtualMachineDisks) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(virtualmachinedisksResource, c.ns, opts)) - -} - -// Create takes the representation of a virtualMachineDisk and creates it. Returns the server's representation of the virtualMachineDisk, and an error, if there is any. -func (c *FakeVirtualMachineDisks) Create(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.CreateOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(virtualmachinedisksResource, c.ns, virtualMachineDisk), &v1alpha2.VirtualMachineDisk{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineDisk), err -} - -// Update takes the representation of a virtualMachineDisk and updates it. Returns the server's representation of the virtualMachineDisk, and an error, if there is any. -func (c *FakeVirtualMachineDisks) Update(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.UpdateOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(virtualmachinedisksResource, c.ns, virtualMachineDisk), &v1alpha2.VirtualMachineDisk{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineDisk), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeVirtualMachineDisks) UpdateStatus(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.UpdateOptions) (*v1alpha2.VirtualMachineDisk, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(virtualmachinedisksResource, "status", c.ns, virtualMachineDisk), &v1alpha2.VirtualMachineDisk{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineDisk), err -} - -// Delete takes name of the virtualMachineDisk and deletes it. Returns an error if one occurs. -func (c *FakeVirtualMachineDisks) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(virtualmachinedisksResource, c.ns, name, opts), &v1alpha2.VirtualMachineDisk{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeVirtualMachineDisks) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(virtualmachinedisksResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha2.VirtualMachineDiskList{}) - return err -} - -// Patch applies the patch and returns the patched virtualMachineDisk. -func (c *FakeVirtualMachineDisks) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualMachineDisk, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(virtualmachinedisksResource, c.ns, name, pt, data, subresources...), &v1alpha2.VirtualMachineDisk{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineDisk), err -} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualmachineimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualmachineimage.go deleted file mode 100644 index 5dbf3d30a..000000000 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/fake/fake_virtualmachineimage.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeVirtualMachineImages implements VirtualMachineImageInterface -type FakeVirtualMachineImages struct { - Fake *FakeVirtualizationV1alpha2 - ns string -} - -var virtualmachineimagesResource = v1alpha2.SchemeGroupVersion.WithResource("virtualmachineimages") - -var virtualmachineimagesKind = v1alpha2.SchemeGroupVersion.WithKind("VirtualMachineImage") - -// Get takes name of the virtualMachineImage, and returns the corresponding virtualMachineImage object, and an error if there is any. -func (c *FakeVirtualMachineImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(virtualmachineimagesResource, c.ns, name), &v1alpha2.VirtualMachineImage{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineImage), err -} - -// List takes label and field selectors, and returns the list of VirtualMachineImages that match those selectors. -func (c *FakeVirtualMachineImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualMachineImageList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(virtualmachineimagesResource, virtualmachineimagesKind, c.ns, opts), &v1alpha2.VirtualMachineImageList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha2.VirtualMachineImageList{ListMeta: obj.(*v1alpha2.VirtualMachineImageList).ListMeta} - for _, item := range obj.(*v1alpha2.VirtualMachineImageList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested virtualMachineImages. -func (c *FakeVirtualMachineImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(virtualmachineimagesResource, c.ns, opts)) - -} - -// Create takes the representation of a virtualMachineImage and creates it. Returns the server's representation of the virtualMachineImage, and an error, if there is any. -func (c *FakeVirtualMachineImages) Create(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.CreateOptions) (result *v1alpha2.VirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(virtualmachineimagesResource, c.ns, virtualMachineImage), &v1alpha2.VirtualMachineImage{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineImage), err -} - -// Update takes the representation of a virtualMachineImage and updates it. Returns the server's representation of the virtualMachineImage, and an error, if there is any. -func (c *FakeVirtualMachineImages) Update(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.UpdateOptions) (result *v1alpha2.VirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(virtualmachineimagesResource, c.ns, virtualMachineImage), &v1alpha2.VirtualMachineImage{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineImage), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeVirtualMachineImages) UpdateStatus(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.UpdateOptions) (*v1alpha2.VirtualMachineImage, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(virtualmachineimagesResource, "status", c.ns, virtualMachineImage), &v1alpha2.VirtualMachineImage{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineImage), err -} - -// Delete takes name of the virtualMachineImage and deletes it. Returns an error if one occurs. -func (c *FakeVirtualMachineImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(virtualmachineimagesResource, c.ns, name, opts), &v1alpha2.VirtualMachineImage{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeVirtualMachineImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(virtualmachineimagesResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha2.VirtualMachineImageList{}) - return err -} - -// Patch applies the patch and returns the patched virtualMachineImage. -func (c *FakeVirtualMachineImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualMachineImage, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(virtualmachineimagesResource, c.ns, name, pt, data, subresources...), &v1alpha2.VirtualMachineImage{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha2.VirtualMachineImage), err -} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/generated_expansion.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/generated_expansion.go index 1c6c93643..b902f022d 100644 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/generated_expansion.go +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/generated_expansion.go @@ -17,7 +17,11 @@ limitations under the License. package v1alpha2 -type ClusterVirtualMachineImageExpansion interface{} +type ClusterVirtualImageExpansion interface{} + +type VirtualDiskExpansion interface{} + +type VirtualImageExpansion interface{} type VirtualMachineExpansion interface{} @@ -25,12 +29,8 @@ type VirtualMachineBlockDeviceAttachmentExpansion interface{} type VirtualMachineCPUModelExpansion interface{} -type VirtualMachineDiskExpansion interface{} - type VirtualMachineIPAddressClaimExpansion interface{} type VirtualMachineIPAddressLeaseExpansion interface{} -type VirtualMachineImageExpansion interface{} - type VirtualMachineOperationExpansion interface{} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualdisk.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualdisk.go new file mode 100644 index 000000000..925c71daf --- /dev/null +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualdisk.go @@ -0,0 +1,194 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "context" + "time" + + scheme "github.com/deckhouse/virtualization/api/client/generated/clientset/versioned/scheme" + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VirtualDisksGetter has a method to return a VirtualDiskInterface. +// A group's client should implement this interface. +type VirtualDisksGetter interface { + VirtualDisks(namespace string) VirtualDiskInterface +} + +// VirtualDiskInterface has methods to work with VirtualDisk resources. +type VirtualDiskInterface interface { + Create(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.CreateOptions) (*v1alpha2.VirtualDisk, error) + Update(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.UpdateOptions) (*v1alpha2.VirtualDisk, error) + UpdateStatus(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.UpdateOptions) (*v1alpha2.VirtualDisk, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.VirtualDisk, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.VirtualDiskList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualDisk, err error) + VirtualDiskExpansion +} + +// virtualDisks implements VirtualDiskInterface +type virtualDisks struct { + client rest.Interface + ns string +} + +// newVirtualDisks returns a VirtualDisks +func newVirtualDisks(c *VirtualizationV1alpha2Client, namespace string) *virtualDisks { + return &virtualDisks{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the virtualDisk, and returns the corresponding virtualDisk object, and an error if there is any. +func (c *virtualDisks) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualDisk, err error) { + result = &v1alpha2.VirtualDisk{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualdisks"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VirtualDisks that match those selectors. +func (c *virtualDisks) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualDiskList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha2.VirtualDiskList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualdisks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested virtualDisks. +func (c *virtualDisks) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("virtualdisks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a virtualDisk and creates it. Returns the server's representation of the virtualDisk, and an error, if there is any. +func (c *virtualDisks) Create(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.CreateOptions) (result *v1alpha2.VirtualDisk, err error) { + result = &v1alpha2.VirtualDisk{} + err = c.client.Post(). + Namespace(c.ns). + Resource("virtualdisks"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualDisk). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a virtualDisk and updates it. Returns the server's representation of the virtualDisk, and an error, if there is any. +func (c *virtualDisks) Update(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.UpdateOptions) (result *v1alpha2.VirtualDisk, err error) { + result = &v1alpha2.VirtualDisk{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualdisks"). + Name(virtualDisk.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualDisk). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *virtualDisks) UpdateStatus(ctx context.Context, virtualDisk *v1alpha2.VirtualDisk, opts v1.UpdateOptions) (result *v1alpha2.VirtualDisk, err error) { + result = &v1alpha2.VirtualDisk{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualdisks"). + Name(virtualDisk.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualDisk). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the virtualDisk and deletes it. Returns an error if one occurs. +func (c *virtualDisks) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualdisks"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *virtualDisks) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualdisks"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched virtualDisk. +func (c *virtualDisks) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualDisk, err error) { + result = &v1alpha2.VirtualDisk{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("virtualdisks"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualimage.go new file mode 100644 index 000000000..6d1a96925 --- /dev/null +++ b/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualimage.go @@ -0,0 +1,194 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "context" + "time" + + scheme "github.com/deckhouse/virtualization/api/client/generated/clientset/versioned/scheme" + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VirtualImagesGetter has a method to return a VirtualImageInterface. +// A group's client should implement this interface. +type VirtualImagesGetter interface { + VirtualImages(namespace string) VirtualImageInterface +} + +// VirtualImageInterface has methods to work with VirtualImage resources. +type VirtualImageInterface interface { + Create(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.CreateOptions) (*v1alpha2.VirtualImage, error) + Update(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.UpdateOptions) (*v1alpha2.VirtualImage, error) + UpdateStatus(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.UpdateOptions) (*v1alpha2.VirtualImage, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.VirtualImage, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.VirtualImageList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualImage, err error) + VirtualImageExpansion +} + +// virtualImages implements VirtualImageInterface +type virtualImages struct { + client rest.Interface + ns string +} + +// newVirtualImages returns a VirtualImages +func newVirtualImages(c *VirtualizationV1alpha2Client, namespace string) *virtualImages { + return &virtualImages{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the virtualImage, and returns the corresponding virtualImage object, and an error if there is any. +func (c *virtualImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualImage, err error) { + result = &v1alpha2.VirtualImage{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualimages"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VirtualImages that match those selectors. +func (c *virtualImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualImageList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha2.VirtualImageList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualimages"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested virtualImages. +func (c *virtualImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("virtualimages"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a virtualImage and creates it. Returns the server's representation of the virtualImage, and an error, if there is any. +func (c *virtualImages) Create(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.CreateOptions) (result *v1alpha2.VirtualImage, err error) { + result = &v1alpha2.VirtualImage{} + err = c.client.Post(). + Namespace(c.ns). + Resource("virtualimages"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualImage). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a virtualImage and updates it. Returns the server's representation of the virtualImage, and an error, if there is any. +func (c *virtualImages) Update(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.UpdateOptions) (result *v1alpha2.VirtualImage, err error) { + result = &v1alpha2.VirtualImage{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualimages"). + Name(virtualImage.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualImage). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *virtualImages) UpdateStatus(ctx context.Context, virtualImage *v1alpha2.VirtualImage, opts v1.UpdateOptions) (result *v1alpha2.VirtualImage, err error) { + result = &v1alpha2.VirtualImage{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualimages"). + Name(virtualImage.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualImage). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the virtualImage and deletes it. Returns an error if one occurs. +func (c *virtualImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualimages"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *virtualImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualimages"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched virtualImage. +func (c *virtualImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualImage, err error) { + result = &v1alpha2.VirtualImage{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("virtualimages"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualmachinedisk.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualmachinedisk.go deleted file mode 100644 index 038ec6c62..000000000 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualmachinedisk.go +++ /dev/null @@ -1,194 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha2 - -import ( - "context" - "time" - - scheme "github.com/deckhouse/virtualization/api/client/generated/clientset/versioned/scheme" - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// VirtualMachineDisksGetter has a method to return a VirtualMachineDiskInterface. -// A group's client should implement this interface. -type VirtualMachineDisksGetter interface { - VirtualMachineDisks(namespace string) VirtualMachineDiskInterface -} - -// VirtualMachineDiskInterface has methods to work with VirtualMachineDisk resources. -type VirtualMachineDiskInterface interface { - Create(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.CreateOptions) (*v1alpha2.VirtualMachineDisk, error) - Update(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.UpdateOptions) (*v1alpha2.VirtualMachineDisk, error) - UpdateStatus(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.UpdateOptions) (*v1alpha2.VirtualMachineDisk, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.VirtualMachineDisk, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.VirtualMachineDiskList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualMachineDisk, err error) - VirtualMachineDiskExpansion -} - -// virtualMachineDisks implements VirtualMachineDiskInterface -type virtualMachineDisks struct { - client rest.Interface - ns string -} - -// newVirtualMachineDisks returns a VirtualMachineDisks -func newVirtualMachineDisks(c *VirtualizationV1alpha2Client, namespace string) *virtualMachineDisks { - return &virtualMachineDisks{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the virtualMachineDisk, and returns the corresponding virtualMachineDisk object, and an error if there is any. -func (c *virtualMachineDisks) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - result = &v1alpha2.VirtualMachineDisk{} - err = c.client.Get(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of VirtualMachineDisks that match those selectors. -func (c *virtualMachineDisks) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualMachineDiskList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha2.VirtualMachineDiskList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested virtualMachineDisks. -func (c *virtualMachineDisks) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a virtualMachineDisk and creates it. Returns the server's representation of the virtualMachineDisk, and an error, if there is any. -func (c *virtualMachineDisks) Create(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.CreateOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - result = &v1alpha2.VirtualMachineDisk{} - err = c.client.Post(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(virtualMachineDisk). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a virtualMachineDisk and updates it. Returns the server's representation of the virtualMachineDisk, and an error, if there is any. -func (c *virtualMachineDisks) Update(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.UpdateOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - result = &v1alpha2.VirtualMachineDisk{} - err = c.client.Put(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - Name(virtualMachineDisk.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(virtualMachineDisk). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *virtualMachineDisks) UpdateStatus(ctx context.Context, virtualMachineDisk *v1alpha2.VirtualMachineDisk, opts v1.UpdateOptions) (result *v1alpha2.VirtualMachineDisk, err error) { - result = &v1alpha2.VirtualMachineDisk{} - err = c.client.Put(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - Name(virtualMachineDisk.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(virtualMachineDisk). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the virtualMachineDisk and deletes it. Returns an error if one occurs. -func (c *virtualMachineDisks) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *virtualMachineDisks) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("virtualmachinedisks"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched virtualMachineDisk. -func (c *virtualMachineDisks) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualMachineDisk, err error) { - result = &v1alpha2.VirtualMachineDisk{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("virtualmachinedisks"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualmachineimage.go b/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualmachineimage.go deleted file mode 100644 index 03a3e3177..000000000 --- a/api/client/generated/clientset/versioned/typed/core/v1alpha2/virtualmachineimage.go +++ /dev/null @@ -1,194 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha2 - -import ( - "context" - "time" - - scheme "github.com/deckhouse/virtualization/api/client/generated/clientset/versioned/scheme" - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// VirtualMachineImagesGetter has a method to return a VirtualMachineImageInterface. -// A group's client should implement this interface. -type VirtualMachineImagesGetter interface { - VirtualMachineImages(namespace string) VirtualMachineImageInterface -} - -// VirtualMachineImageInterface has methods to work with VirtualMachineImage resources. -type VirtualMachineImageInterface interface { - Create(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.CreateOptions) (*v1alpha2.VirtualMachineImage, error) - Update(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.UpdateOptions) (*v1alpha2.VirtualMachineImage, error) - UpdateStatus(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.UpdateOptions) (*v1alpha2.VirtualMachineImage, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.VirtualMachineImage, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha2.VirtualMachineImageList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualMachineImage, err error) - VirtualMachineImageExpansion -} - -// virtualMachineImages implements VirtualMachineImageInterface -type virtualMachineImages struct { - client rest.Interface - ns string -} - -// newVirtualMachineImages returns a VirtualMachineImages -func newVirtualMachineImages(c *VirtualizationV1alpha2Client, namespace string) *virtualMachineImages { - return &virtualMachineImages{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the virtualMachineImage, and returns the corresponding virtualMachineImage object, and an error if there is any. -func (c *virtualMachineImages) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.VirtualMachineImage, err error) { - result = &v1alpha2.VirtualMachineImage{} - err = c.client.Get(). - Namespace(c.ns). - Resource("virtualmachineimages"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of VirtualMachineImages that match those selectors. -func (c *virtualMachineImages) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.VirtualMachineImageList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha2.VirtualMachineImageList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("virtualmachineimages"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested virtualMachineImages. -func (c *virtualMachineImages) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("virtualmachineimages"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a virtualMachineImage and creates it. Returns the server's representation of the virtualMachineImage, and an error, if there is any. -func (c *virtualMachineImages) Create(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.CreateOptions) (result *v1alpha2.VirtualMachineImage, err error) { - result = &v1alpha2.VirtualMachineImage{} - err = c.client.Post(). - Namespace(c.ns). - Resource("virtualmachineimages"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(virtualMachineImage). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a virtualMachineImage and updates it. Returns the server's representation of the virtualMachineImage, and an error, if there is any. -func (c *virtualMachineImages) Update(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.UpdateOptions) (result *v1alpha2.VirtualMachineImage, err error) { - result = &v1alpha2.VirtualMachineImage{} - err = c.client.Put(). - Namespace(c.ns). - Resource("virtualmachineimages"). - Name(virtualMachineImage.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(virtualMachineImage). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *virtualMachineImages) UpdateStatus(ctx context.Context, virtualMachineImage *v1alpha2.VirtualMachineImage, opts v1.UpdateOptions) (result *v1alpha2.VirtualMachineImage, err error) { - result = &v1alpha2.VirtualMachineImage{} - err = c.client.Put(). - Namespace(c.ns). - Resource("virtualmachineimages"). - Name(virtualMachineImage.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(virtualMachineImage). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the virtualMachineImage and deletes it. Returns an error if one occurs. -func (c *virtualMachineImages) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("virtualmachineimages"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *virtualMachineImages) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("virtualmachineimages"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched virtualMachineImage. -func (c *virtualMachineImages) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.VirtualMachineImage, err error) { - result = &v1alpha2.VirtualMachineImage{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("virtualmachineimages"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/api/client/generated/informers/externalversions/core/v1alpha2/virtualmachineimage.go b/api/client/generated/informers/externalversions/core/v1alpha2/clustervirtualimage.go similarity index 57% rename from api/client/generated/informers/externalversions/core/v1alpha2/virtualmachineimage.go rename to api/client/generated/informers/externalversions/core/v1alpha2/clustervirtualimage.go index caf4d99d2..aab644c55 100644 --- a/api/client/generated/informers/externalversions/core/v1alpha2/virtualmachineimage.go +++ b/api/client/generated/informers/externalversions/core/v1alpha2/clustervirtualimage.go @@ -31,59 +31,58 @@ import ( cache "k8s.io/client-go/tools/cache" ) -// VirtualMachineImageInformer provides access to a shared informer and lister for -// VirtualMachineImages. -type VirtualMachineImageInformer interface { +// ClusterVirtualImageInformer provides access to a shared informer and lister for +// ClusterVirtualImages. +type ClusterVirtualImageInformer interface { Informer() cache.SharedIndexInformer - Lister() v1alpha2.VirtualMachineImageLister + Lister() v1alpha2.ClusterVirtualImageLister } -type virtualMachineImageInformer struct { +type clusterVirtualImageInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string } -// NewVirtualMachineImageInformer constructs a new informer for VirtualMachineImage type. +// NewClusterVirtualImageInformer constructs a new informer for ClusterVirtualImage type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewVirtualMachineImageInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredVirtualMachineImageInformer(client, namespace, resyncPeriod, indexers, nil) +func NewClusterVirtualImageInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredClusterVirtualImageInformer(client, resyncPeriod, indexers, nil) } -// NewFilteredVirtualMachineImageInformer constructs a new informer for VirtualMachineImage type. +// NewFilteredClusterVirtualImageInformer constructs a new informer for ClusterVirtualImage type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewFilteredVirtualMachineImageInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredClusterVirtualImageInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.VirtualizationV1alpha2().VirtualMachineImages(namespace).List(context.TODO(), options) + return client.VirtualizationV1alpha2().ClusterVirtualImages().List(context.TODO(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.VirtualizationV1alpha2().VirtualMachineImages(namespace).Watch(context.TODO(), options) + return client.VirtualizationV1alpha2().ClusterVirtualImages().Watch(context.TODO(), options) }, }, - &corev1alpha2.VirtualMachineImage{}, + &corev1alpha2.ClusterVirtualImage{}, resyncPeriod, indexers, ) } -func (f *virtualMachineImageInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredVirtualMachineImageInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *clusterVirtualImageInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredClusterVirtualImageInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *virtualMachineImageInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&corev1alpha2.VirtualMachineImage{}, f.defaultInformer) +func (f *clusterVirtualImageInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1alpha2.ClusterVirtualImage{}, f.defaultInformer) } -func (f *virtualMachineImageInformer) Lister() v1alpha2.VirtualMachineImageLister { - return v1alpha2.NewVirtualMachineImageLister(f.Informer().GetIndexer()) +func (f *clusterVirtualImageInformer) Lister() v1alpha2.ClusterVirtualImageLister { + return v1alpha2.NewClusterVirtualImageLister(f.Informer().GetIndexer()) } diff --git a/api/client/generated/informers/externalversions/core/v1alpha2/interface.go b/api/client/generated/informers/externalversions/core/v1alpha2/interface.go index e66479553..63ef149cf 100644 --- a/api/client/generated/informers/externalversions/core/v1alpha2/interface.go +++ b/api/client/generated/informers/externalversions/core/v1alpha2/interface.go @@ -23,22 +23,22 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { - // ClusterVirtualMachineImages returns a ClusterVirtualMachineImageInformer. - ClusterVirtualMachineImages() ClusterVirtualMachineImageInformer + // ClusterVirtualImages returns a ClusterVirtualImageInformer. + ClusterVirtualImages() ClusterVirtualImageInformer + // VirtualDisks returns a VirtualDiskInformer. + VirtualDisks() VirtualDiskInformer + // VirtualImages returns a VirtualImageInformer. + VirtualImages() VirtualImageInformer // VirtualMachines returns a VirtualMachineInformer. VirtualMachines() VirtualMachineInformer // VirtualMachineBlockDeviceAttachments returns a VirtualMachineBlockDeviceAttachmentInformer. VirtualMachineBlockDeviceAttachments() VirtualMachineBlockDeviceAttachmentInformer // VirtualMachineCPUModels returns a VirtualMachineCPUModelInformer. VirtualMachineCPUModels() VirtualMachineCPUModelInformer - // VirtualMachineDisks returns a VirtualMachineDiskInformer. - VirtualMachineDisks() VirtualMachineDiskInformer // VirtualMachineIPAddressClaims returns a VirtualMachineIPAddressClaimInformer. VirtualMachineIPAddressClaims() VirtualMachineIPAddressClaimInformer // VirtualMachineIPAddressLeases returns a VirtualMachineIPAddressLeaseInformer. VirtualMachineIPAddressLeases() VirtualMachineIPAddressLeaseInformer - // VirtualMachineImages returns a VirtualMachineImageInformer. - VirtualMachineImages() VirtualMachineImageInformer // VirtualMachineOperations returns a VirtualMachineOperationInformer. VirtualMachineOperations() VirtualMachineOperationInformer } @@ -54,9 +54,19 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// ClusterVirtualMachineImages returns a ClusterVirtualMachineImageInformer. -func (v *version) ClusterVirtualMachineImages() ClusterVirtualMachineImageInformer { - return &clusterVirtualMachineImageInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +// ClusterVirtualImages returns a ClusterVirtualImageInformer. +func (v *version) ClusterVirtualImages() ClusterVirtualImageInformer { + return &clusterVirtualImageInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// VirtualDisks returns a VirtualDiskInformer. +func (v *version) VirtualDisks() VirtualDiskInformer { + return &virtualDiskInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// VirtualImages returns a VirtualImageInformer. +func (v *version) VirtualImages() VirtualImageInformer { + return &virtualImageInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } // VirtualMachines returns a VirtualMachineInformer. @@ -74,11 +84,6 @@ func (v *version) VirtualMachineCPUModels() VirtualMachineCPUModelInformer { return &virtualMachineCPUModelInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } -// VirtualMachineDisks returns a VirtualMachineDiskInformer. -func (v *version) VirtualMachineDisks() VirtualMachineDiskInformer { - return &virtualMachineDiskInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} - // VirtualMachineIPAddressClaims returns a VirtualMachineIPAddressClaimInformer. func (v *version) VirtualMachineIPAddressClaims() VirtualMachineIPAddressClaimInformer { return &virtualMachineIPAddressClaimInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} @@ -89,11 +94,6 @@ func (v *version) VirtualMachineIPAddressLeases() VirtualMachineIPAddressLeaseIn return &virtualMachineIPAddressLeaseInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } -// VirtualMachineImages returns a VirtualMachineImageInformer. -func (v *version) VirtualMachineImages() VirtualMachineImageInformer { - return &virtualMachineImageInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} - // VirtualMachineOperations returns a VirtualMachineOperationInformer. func (v *version) VirtualMachineOperations() VirtualMachineOperationInformer { return &virtualMachineOperationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/api/client/generated/informers/externalversions/core/v1alpha2/virtualmachinedisk.go b/api/client/generated/informers/externalversions/core/v1alpha2/virtualdisk.go similarity index 54% rename from api/client/generated/informers/externalversions/core/v1alpha2/virtualmachinedisk.go rename to api/client/generated/informers/externalversions/core/v1alpha2/virtualdisk.go index e66232968..0cd4af03b 100644 --- a/api/client/generated/informers/externalversions/core/v1alpha2/virtualmachinedisk.go +++ b/api/client/generated/informers/externalversions/core/v1alpha2/virtualdisk.go @@ -31,59 +31,59 @@ import ( cache "k8s.io/client-go/tools/cache" ) -// VirtualMachineDiskInformer provides access to a shared informer and lister for -// VirtualMachineDisks. -type VirtualMachineDiskInformer interface { +// VirtualDiskInformer provides access to a shared informer and lister for +// VirtualDisks. +type VirtualDiskInformer interface { Informer() cache.SharedIndexInformer - Lister() v1alpha2.VirtualMachineDiskLister + Lister() v1alpha2.VirtualDiskLister } -type virtualMachineDiskInformer struct { +type virtualDiskInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc namespace string } -// NewVirtualMachineDiskInformer constructs a new informer for VirtualMachineDisk type. +// NewVirtualDiskInformer constructs a new informer for VirtualDisk type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewVirtualMachineDiskInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredVirtualMachineDiskInformer(client, namespace, resyncPeriod, indexers, nil) +func NewVirtualDiskInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVirtualDiskInformer(client, namespace, resyncPeriod, indexers, nil) } -// NewFilteredVirtualMachineDiskInformer constructs a new informer for VirtualMachineDisk type. +// NewFilteredVirtualDiskInformer constructs a new informer for VirtualDisk type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewFilteredVirtualMachineDiskInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredVirtualDiskInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.VirtualizationV1alpha2().VirtualMachineDisks(namespace).List(context.TODO(), options) + return client.VirtualizationV1alpha2().VirtualDisks(namespace).List(context.TODO(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.VirtualizationV1alpha2().VirtualMachineDisks(namespace).Watch(context.TODO(), options) + return client.VirtualizationV1alpha2().VirtualDisks(namespace).Watch(context.TODO(), options) }, }, - &corev1alpha2.VirtualMachineDisk{}, + &corev1alpha2.VirtualDisk{}, resyncPeriod, indexers, ) } -func (f *virtualMachineDiskInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredVirtualMachineDiskInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *virtualDiskInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVirtualDiskInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *virtualMachineDiskInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&corev1alpha2.VirtualMachineDisk{}, f.defaultInformer) +func (f *virtualDiskInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1alpha2.VirtualDisk{}, f.defaultInformer) } -func (f *virtualMachineDiskInformer) Lister() v1alpha2.VirtualMachineDiskLister { - return v1alpha2.NewVirtualMachineDiskLister(f.Informer().GetIndexer()) +func (f *virtualDiskInformer) Lister() v1alpha2.VirtualDiskLister { + return v1alpha2.NewVirtualDiskLister(f.Informer().GetIndexer()) } diff --git a/api/client/generated/informers/externalversions/core/v1alpha2/clustervirtualmachineimage.go b/api/client/generated/informers/externalversions/core/v1alpha2/virtualimage.go similarity index 53% rename from api/client/generated/informers/externalversions/core/v1alpha2/clustervirtualmachineimage.go rename to api/client/generated/informers/externalversions/core/v1alpha2/virtualimage.go index 580a4bc2b..95fd99b9c 100644 --- a/api/client/generated/informers/externalversions/core/v1alpha2/clustervirtualmachineimage.go +++ b/api/client/generated/informers/externalversions/core/v1alpha2/virtualimage.go @@ -31,58 +31,59 @@ import ( cache "k8s.io/client-go/tools/cache" ) -// ClusterVirtualMachineImageInformer provides access to a shared informer and lister for -// ClusterVirtualMachineImages. -type ClusterVirtualMachineImageInformer interface { +// VirtualImageInformer provides access to a shared informer and lister for +// VirtualImages. +type VirtualImageInformer interface { Informer() cache.SharedIndexInformer - Lister() v1alpha2.ClusterVirtualMachineImageLister + Lister() v1alpha2.VirtualImageLister } -type clusterVirtualMachineImageInformer struct { +type virtualImageInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string } -// NewClusterVirtualMachineImageInformer constructs a new informer for ClusterVirtualMachineImage type. +// NewVirtualImageInformer constructs a new informer for VirtualImage type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewClusterVirtualMachineImageInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredClusterVirtualMachineImageInformer(client, resyncPeriod, indexers, nil) +func NewVirtualImageInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVirtualImageInformer(client, namespace, resyncPeriod, indexers, nil) } -// NewFilteredClusterVirtualMachineImageInformer constructs a new informer for ClusterVirtualMachineImage type. +// NewFilteredVirtualImageInformer constructs a new informer for VirtualImage type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewFilteredClusterVirtualMachineImageInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredVirtualImageInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.VirtualizationV1alpha2().ClusterVirtualMachineImages().List(context.TODO(), options) + return client.VirtualizationV1alpha2().VirtualImages(namespace).List(context.TODO(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.VirtualizationV1alpha2().ClusterVirtualMachineImages().Watch(context.TODO(), options) + return client.VirtualizationV1alpha2().VirtualImages(namespace).Watch(context.TODO(), options) }, }, - &corev1alpha2.ClusterVirtualMachineImage{}, + &corev1alpha2.VirtualImage{}, resyncPeriod, indexers, ) } -func (f *clusterVirtualMachineImageInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredClusterVirtualMachineImageInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *virtualImageInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVirtualImageInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *clusterVirtualMachineImageInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&corev1alpha2.ClusterVirtualMachineImage{}, f.defaultInformer) +func (f *virtualImageInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1alpha2.VirtualImage{}, f.defaultInformer) } -func (f *clusterVirtualMachineImageInformer) Lister() v1alpha2.ClusterVirtualMachineImageLister { - return v1alpha2.NewClusterVirtualMachineImageLister(f.Informer().GetIndexer()) +func (f *virtualImageInformer) Lister() v1alpha2.VirtualImageLister { + return v1alpha2.NewVirtualImageLister(f.Informer().GetIndexer()) } diff --git a/api/client/generated/informers/externalversions/generic.go b/api/client/generated/informers/externalversions/generic.go index 2cd6f417f..768d60d49 100644 --- a/api/client/generated/informers/externalversions/generic.go +++ b/api/client/generated/informers/externalversions/generic.go @@ -52,22 +52,22 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=virtualization.deckhouse.io, Version=v1alpha2 - case v1alpha2.SchemeGroupVersion.WithResource("clustervirtualmachineimages"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().ClusterVirtualMachineImages().Informer()}, nil + case v1alpha2.SchemeGroupVersion.WithResource("clustervirtualimages"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().ClusterVirtualImages().Informer()}, nil + case v1alpha2.SchemeGroupVersion.WithResource("virtualdisks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualDisks().Informer()}, nil + case v1alpha2.SchemeGroupVersion.WithResource("virtualimages"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualImages().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("virtualmachines"): return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachines().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("virtualmachineblockdeviceattachments"): return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineBlockDeviceAttachments().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("virtualmachinecpumodels"): return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineCPUModels().Informer()}, nil - case v1alpha2.SchemeGroupVersion.WithResource("virtualmachinedisks"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineDisks().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("virtualmachineipaddressclaims"): return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineIPAddressClaims().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("virtualmachineipaddressleases"): return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineIPAddressLeases().Informer()}, nil - case v1alpha2.SchemeGroupVersion.WithResource("virtualmachineimages"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineImages().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("virtualmachineoperations"): return &genericInformer{resource: resource.GroupResource(), informer: f.Virtualization().V1alpha2().VirtualMachineOperations().Informer()}, nil diff --git a/api/client/generated/listers/core/v1alpha2/clustervirtualimage.go b/api/client/generated/listers/core/v1alpha2/clustervirtualimage.go new file mode 100644 index 000000000..45f969e4d --- /dev/null +++ b/api/client/generated/listers/core/v1alpha2/clustervirtualimage.go @@ -0,0 +1,67 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ClusterVirtualImageLister helps list ClusterVirtualImages. +// All objects returned here must be treated as read-only. +type ClusterVirtualImageLister interface { + // List lists all ClusterVirtualImages in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.ClusterVirtualImage, err error) + // Get retrieves the ClusterVirtualImage from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha2.ClusterVirtualImage, error) + ClusterVirtualImageListerExpansion +} + +// clusterVirtualImageLister implements the ClusterVirtualImageLister interface. +type clusterVirtualImageLister struct { + indexer cache.Indexer +} + +// NewClusterVirtualImageLister returns a new ClusterVirtualImageLister. +func NewClusterVirtualImageLister(indexer cache.Indexer) ClusterVirtualImageLister { + return &clusterVirtualImageLister{indexer: indexer} +} + +// List lists all ClusterVirtualImages in the indexer. +func (s *clusterVirtualImageLister) List(selector labels.Selector) (ret []*v1alpha2.ClusterVirtualImage, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.ClusterVirtualImage)) + }) + return ret, err +} + +// Get retrieves the ClusterVirtualImage from the index for a given name. +func (s *clusterVirtualImageLister) Get(name string) (*v1alpha2.ClusterVirtualImage, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("clustervirtualimage"), name) + } + return obj.(*v1alpha2.ClusterVirtualImage), nil +} diff --git a/api/client/generated/listers/core/v1alpha2/clustervirtualmachineimage.go b/api/client/generated/listers/core/v1alpha2/clustervirtualmachineimage.go deleted file mode 100644 index b1970ad62..000000000 --- a/api/client/generated/listers/core/v1alpha2/clustervirtualmachineimage.go +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha2 - -import ( - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// ClusterVirtualMachineImageLister helps list ClusterVirtualMachineImages. -// All objects returned here must be treated as read-only. -type ClusterVirtualMachineImageLister interface { - // List lists all ClusterVirtualMachineImages in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.ClusterVirtualMachineImage, err error) - // Get retrieves the ClusterVirtualMachineImage from the index for a given name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha2.ClusterVirtualMachineImage, error) - ClusterVirtualMachineImageListerExpansion -} - -// clusterVirtualMachineImageLister implements the ClusterVirtualMachineImageLister interface. -type clusterVirtualMachineImageLister struct { - indexer cache.Indexer -} - -// NewClusterVirtualMachineImageLister returns a new ClusterVirtualMachineImageLister. -func NewClusterVirtualMachineImageLister(indexer cache.Indexer) ClusterVirtualMachineImageLister { - return &clusterVirtualMachineImageLister{indexer: indexer} -} - -// List lists all ClusterVirtualMachineImages in the indexer. -func (s *clusterVirtualMachineImageLister) List(selector labels.Selector) (ret []*v1alpha2.ClusterVirtualMachineImage, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.ClusterVirtualMachineImage)) - }) - return ret, err -} - -// Get retrieves the ClusterVirtualMachineImage from the index for a given name. -func (s *clusterVirtualMachineImageLister) Get(name string) (*v1alpha2.ClusterVirtualMachineImage, error) { - obj, exists, err := s.indexer.GetByKey(name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha2.Resource("clustervirtualmachineimage"), name) - } - return obj.(*v1alpha2.ClusterVirtualMachineImage), nil -} diff --git a/api/client/generated/listers/core/v1alpha2/expansion_generated.go b/api/client/generated/listers/core/v1alpha2/expansion_generated.go index 048b3e5b9..3f10e3f28 100644 --- a/api/client/generated/listers/core/v1alpha2/expansion_generated.go +++ b/api/client/generated/listers/core/v1alpha2/expansion_generated.go @@ -17,9 +17,25 @@ limitations under the License. package v1alpha2 -// ClusterVirtualMachineImageListerExpansion allows custom methods to be added to -// ClusterVirtualMachineImageLister. -type ClusterVirtualMachineImageListerExpansion interface{} +// ClusterVirtualImageListerExpansion allows custom methods to be added to +// ClusterVirtualImageLister. +type ClusterVirtualImageListerExpansion interface{} + +// VirtualDiskListerExpansion allows custom methods to be added to +// VirtualDiskLister. +type VirtualDiskListerExpansion interface{} + +// VirtualDiskNamespaceListerExpansion allows custom methods to be added to +// VirtualDiskNamespaceLister. +type VirtualDiskNamespaceListerExpansion interface{} + +// VirtualImageListerExpansion allows custom methods to be added to +// VirtualImageLister. +type VirtualImageListerExpansion interface{} + +// VirtualImageNamespaceListerExpansion allows custom methods to be added to +// VirtualImageNamespaceLister. +type VirtualImageNamespaceListerExpansion interface{} // VirtualMachineListerExpansion allows custom methods to be added to // VirtualMachineLister. @@ -41,14 +57,6 @@ type VirtualMachineBlockDeviceAttachmentNamespaceListerExpansion interface{} // VirtualMachineCPUModelLister. type VirtualMachineCPUModelListerExpansion interface{} -// VirtualMachineDiskListerExpansion allows custom methods to be added to -// VirtualMachineDiskLister. -type VirtualMachineDiskListerExpansion interface{} - -// VirtualMachineDiskNamespaceListerExpansion allows custom methods to be added to -// VirtualMachineDiskNamespaceLister. -type VirtualMachineDiskNamespaceListerExpansion interface{} - // VirtualMachineIPAddressClaimListerExpansion allows custom methods to be added to // VirtualMachineIPAddressClaimLister. type VirtualMachineIPAddressClaimListerExpansion interface{} @@ -61,14 +69,6 @@ type VirtualMachineIPAddressClaimNamespaceListerExpansion interface{} // VirtualMachineIPAddressLeaseLister. type VirtualMachineIPAddressLeaseListerExpansion interface{} -// VirtualMachineImageListerExpansion allows custom methods to be added to -// VirtualMachineImageLister. -type VirtualMachineImageListerExpansion interface{} - -// VirtualMachineImageNamespaceListerExpansion allows custom methods to be added to -// VirtualMachineImageNamespaceLister. -type VirtualMachineImageNamespaceListerExpansion interface{} - // VirtualMachineOperationListerExpansion allows custom methods to be added to // VirtualMachineOperationLister. type VirtualMachineOperationListerExpansion interface{} diff --git a/api/client/generated/listers/core/v1alpha2/virtualdisk.go b/api/client/generated/listers/core/v1alpha2/virtualdisk.go new file mode 100644 index 000000000..a19118517 --- /dev/null +++ b/api/client/generated/listers/core/v1alpha2/virtualdisk.go @@ -0,0 +1,98 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VirtualDiskLister helps list VirtualDisks. +// All objects returned here must be treated as read-only. +type VirtualDiskLister interface { + // List lists all VirtualDisks in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.VirtualDisk, err error) + // VirtualDisks returns an object that can list and get VirtualDisks. + VirtualDisks(namespace string) VirtualDiskNamespaceLister + VirtualDiskListerExpansion +} + +// virtualDiskLister implements the VirtualDiskLister interface. +type virtualDiskLister struct { + indexer cache.Indexer +} + +// NewVirtualDiskLister returns a new VirtualDiskLister. +func NewVirtualDiskLister(indexer cache.Indexer) VirtualDiskLister { + return &virtualDiskLister{indexer: indexer} +} + +// List lists all VirtualDisks in the indexer. +func (s *virtualDiskLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualDisk, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.VirtualDisk)) + }) + return ret, err +} + +// VirtualDisks returns an object that can list and get VirtualDisks. +func (s *virtualDiskLister) VirtualDisks(namespace string) VirtualDiskNamespaceLister { + return virtualDiskNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VirtualDiskNamespaceLister helps list and get VirtualDisks. +// All objects returned here must be treated as read-only. +type VirtualDiskNamespaceLister interface { + // List lists all VirtualDisks in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.VirtualDisk, err error) + // Get retrieves the VirtualDisk from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha2.VirtualDisk, error) + VirtualDiskNamespaceListerExpansion +} + +// virtualDiskNamespaceLister implements the VirtualDiskNamespaceLister +// interface. +type virtualDiskNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VirtualDisks in the indexer for a given namespace. +func (s virtualDiskNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualDisk, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.VirtualDisk)) + }) + return ret, err +} + +// Get retrieves the VirtualDisk from the indexer for a given namespace and name. +func (s virtualDiskNamespaceLister) Get(name string) (*v1alpha2.VirtualDisk, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("virtualdisk"), name) + } + return obj.(*v1alpha2.VirtualDisk), nil +} diff --git a/api/client/generated/listers/core/v1alpha2/virtualimage.go b/api/client/generated/listers/core/v1alpha2/virtualimage.go new file mode 100644 index 000000000..48248c922 --- /dev/null +++ b/api/client/generated/listers/core/v1alpha2/virtualimage.go @@ -0,0 +1,98 @@ +/* +Copyright 2022 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VirtualImageLister helps list VirtualImages. +// All objects returned here must be treated as read-only. +type VirtualImageLister interface { + // List lists all VirtualImages in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.VirtualImage, err error) + // VirtualImages returns an object that can list and get VirtualImages. + VirtualImages(namespace string) VirtualImageNamespaceLister + VirtualImageListerExpansion +} + +// virtualImageLister implements the VirtualImageLister interface. +type virtualImageLister struct { + indexer cache.Indexer +} + +// NewVirtualImageLister returns a new VirtualImageLister. +func NewVirtualImageLister(indexer cache.Indexer) VirtualImageLister { + return &virtualImageLister{indexer: indexer} +} + +// List lists all VirtualImages in the indexer. +func (s *virtualImageLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualImage, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.VirtualImage)) + }) + return ret, err +} + +// VirtualImages returns an object that can list and get VirtualImages. +func (s *virtualImageLister) VirtualImages(namespace string) VirtualImageNamespaceLister { + return virtualImageNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VirtualImageNamespaceLister helps list and get VirtualImages. +// All objects returned here must be treated as read-only. +type VirtualImageNamespaceLister interface { + // List lists all VirtualImages in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha2.VirtualImage, err error) + // Get retrieves the VirtualImage from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha2.VirtualImage, error) + VirtualImageNamespaceListerExpansion +} + +// virtualImageNamespaceLister implements the VirtualImageNamespaceLister +// interface. +type virtualImageNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VirtualImages in the indexer for a given namespace. +func (s virtualImageNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualImage, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.VirtualImage)) + }) + return ret, err +} + +// Get retrieves the VirtualImage from the indexer for a given namespace and name. +func (s virtualImageNamespaceLister) Get(name string) (*v1alpha2.VirtualImage, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("virtualimage"), name) + } + return obj.(*v1alpha2.VirtualImage), nil +} diff --git a/api/client/generated/listers/core/v1alpha2/virtualmachinedisk.go b/api/client/generated/listers/core/v1alpha2/virtualmachinedisk.go deleted file mode 100644 index 9a4ac8b98..000000000 --- a/api/client/generated/listers/core/v1alpha2/virtualmachinedisk.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha2 - -import ( - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// VirtualMachineDiskLister helps list VirtualMachineDisks. -// All objects returned here must be treated as read-only. -type VirtualMachineDiskLister interface { - // List lists all VirtualMachineDisks in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineDisk, err error) - // VirtualMachineDisks returns an object that can list and get VirtualMachineDisks. - VirtualMachineDisks(namespace string) VirtualMachineDiskNamespaceLister - VirtualMachineDiskListerExpansion -} - -// virtualMachineDiskLister implements the VirtualMachineDiskLister interface. -type virtualMachineDiskLister struct { - indexer cache.Indexer -} - -// NewVirtualMachineDiskLister returns a new VirtualMachineDiskLister. -func NewVirtualMachineDiskLister(indexer cache.Indexer) VirtualMachineDiskLister { - return &virtualMachineDiskLister{indexer: indexer} -} - -// List lists all VirtualMachineDisks in the indexer. -func (s *virtualMachineDiskLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineDisk, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.VirtualMachineDisk)) - }) - return ret, err -} - -// VirtualMachineDisks returns an object that can list and get VirtualMachineDisks. -func (s *virtualMachineDiskLister) VirtualMachineDisks(namespace string) VirtualMachineDiskNamespaceLister { - return virtualMachineDiskNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// VirtualMachineDiskNamespaceLister helps list and get VirtualMachineDisks. -// All objects returned here must be treated as read-only. -type VirtualMachineDiskNamespaceLister interface { - // List lists all VirtualMachineDisks in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineDisk, err error) - // Get retrieves the VirtualMachineDisk from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha2.VirtualMachineDisk, error) - VirtualMachineDiskNamespaceListerExpansion -} - -// virtualMachineDiskNamespaceLister implements the VirtualMachineDiskNamespaceLister -// interface. -type virtualMachineDiskNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all VirtualMachineDisks in the indexer for a given namespace. -func (s virtualMachineDiskNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineDisk, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.VirtualMachineDisk)) - }) - return ret, err -} - -// Get retrieves the VirtualMachineDisk from the indexer for a given namespace and name. -func (s virtualMachineDiskNamespaceLister) Get(name string) (*v1alpha2.VirtualMachineDisk, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha2.Resource("virtualmachinedisk"), name) - } - return obj.(*v1alpha2.VirtualMachineDisk), nil -} diff --git a/api/client/generated/listers/core/v1alpha2/virtualmachineimage.go b/api/client/generated/listers/core/v1alpha2/virtualmachineimage.go deleted file mode 100644 index 047efafcc..000000000 --- a/api/client/generated/listers/core/v1alpha2/virtualmachineimage.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2022 Flant JSC - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha2 - -import ( - v1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// VirtualMachineImageLister helps list VirtualMachineImages. -// All objects returned here must be treated as read-only. -type VirtualMachineImageLister interface { - // List lists all VirtualMachineImages in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineImage, err error) - // VirtualMachineImages returns an object that can list and get VirtualMachineImages. - VirtualMachineImages(namespace string) VirtualMachineImageNamespaceLister - VirtualMachineImageListerExpansion -} - -// virtualMachineImageLister implements the VirtualMachineImageLister interface. -type virtualMachineImageLister struct { - indexer cache.Indexer -} - -// NewVirtualMachineImageLister returns a new VirtualMachineImageLister. -func NewVirtualMachineImageLister(indexer cache.Indexer) VirtualMachineImageLister { - return &virtualMachineImageLister{indexer: indexer} -} - -// List lists all VirtualMachineImages in the indexer. -func (s *virtualMachineImageLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineImage, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.VirtualMachineImage)) - }) - return ret, err -} - -// VirtualMachineImages returns an object that can list and get VirtualMachineImages. -func (s *virtualMachineImageLister) VirtualMachineImages(namespace string) VirtualMachineImageNamespaceLister { - return virtualMachineImageNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// VirtualMachineImageNamespaceLister helps list and get VirtualMachineImages. -// All objects returned here must be treated as read-only. -type VirtualMachineImageNamespaceLister interface { - // List lists all VirtualMachineImages in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineImage, err error) - // Get retrieves the VirtualMachineImage from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha2.VirtualMachineImage, error) - VirtualMachineImageNamespaceListerExpansion -} - -// virtualMachineImageNamespaceLister implements the VirtualMachineImageNamespaceLister -// interface. -type virtualMachineImageNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all VirtualMachineImages in the indexer for a given namespace. -func (s virtualMachineImageNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.VirtualMachineImage, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha2.VirtualMachineImage)) - }) - return ret, err -} - -// Get retrieves the VirtualMachineImage from the indexer for a given namespace and name. -func (s virtualMachineImageNamespaceLister) Get(name string) (*v1alpha2.VirtualMachineImage, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha2.Resource("virtualmachineimage"), name) - } - return obj.(*v1alpha2.VirtualMachineImage), nil -} diff --git a/api/client/kubeclient/client.go b/api/client/kubeclient/client.go index 3d670081d..dcaab85b4 100644 --- a/api/client/kubeclient/client.go +++ b/api/client/kubeclient/client.go @@ -38,10 +38,10 @@ func init() { } type Client interface { - ClusterVirtualMachineImages() virtualizationv1alpha2.ClusterVirtualMachineImageInterface + ClusterVirtualImages() virtualizationv1alpha2.ClusterVirtualImageInterface VirtualMachines(namespace string) VirtualMachineInterface - VirtualMachineImages(namespace string) virtualizationv1alpha2.VirtualMachineImageInterface - VirtualMachineDisks(namespace string) virtualizationv1alpha2.VirtualMachineDiskInterface + VirtualImages(namespace string) virtualizationv1alpha2.VirtualImageInterface + VirtualDisks(namespace string) virtualizationv1alpha2.VirtualDiskInterface VirtualMachineBlockDeviceAttachments(namespace string) virtualizationv1alpha2.VirtualMachineBlockDeviceAttachmentInterface VirtualMachineIPAddressClaims(namespace string) virtualizationv1alpha2.VirtualMachineIPAddressClaimInterface VirtualMachineIPAddressLeases() virtualizationv1alpha2.VirtualMachineIPAddressLeaseInterface @@ -82,16 +82,16 @@ func (c client) VirtualMachines(namespace string) VirtualMachineInterface { } } -func (c client) ClusterVirtualMachineImages() virtualizationv1alpha2.ClusterVirtualMachineImageInterface { - return c.virtClient.VirtualizationV1alpha2().ClusterVirtualMachineImages() +func (c client) ClusterVirtualImages() virtualizationv1alpha2.ClusterVirtualImageInterface { + return c.virtClient.VirtualizationV1alpha2().ClusterVirtualImages() } -func (c client) VirtualMachineImages(namespace string) virtualizationv1alpha2.VirtualMachineImageInterface { - return c.virtClient.VirtualizationV1alpha2().VirtualMachineImages(namespace) +func (c client) VirtualImages(namespace string) virtualizationv1alpha2.VirtualImageInterface { + return c.virtClient.VirtualizationV1alpha2().VirtualImages(namespace) } -func (c client) VirtualMachineDisks(namespace string) virtualizationv1alpha2.VirtualMachineDiskInterface { - return c.virtClient.VirtualizationV1alpha2().VirtualMachineDisks(namespace) +func (c client) VirtualDisks(namespace string) virtualizationv1alpha2.VirtualDiskInterface { + return c.virtClient.VirtualizationV1alpha2().VirtualDisks(namespace) } func (c client) VirtualMachineBlockDeviceAttachments(namespace string) virtualizationv1alpha2.VirtualMachineBlockDeviceAttachmentInterface { diff --git a/api/core/v1alpha2/block_device.go b/api/core/v1alpha2/block_device.go index 4759161b8..23b19c90b 100644 --- a/api/core/v1alpha2/block_device.go +++ b/api/core/v1alpha2/block_device.go @@ -1,38 +1,22 @@ package v1alpha2 -type BlockDeviceSpec struct { - Type BlockDeviceType `json:"type"` - VirtualMachineImage *ImageDeviceSpec `json:"virtualMachineImage,omitempty"` - ClusterVirtualMachineImage *ClusterImageDeviceSpec `json:"clusterVirtualMachineImage,omitempty"` - VirtualMachineDisk *DiskDeviceSpec `json:"virtualMachineDisk,omitempty"` +type BlockDeviceSpecRef struct { + Kind BlockDeviceKind `json:"kind"` + Name string `json:"name"` } -type BlockDeviceStatus struct { - Type BlockDeviceType `json:"type"` - VirtualMachineImage *ImageDeviceSpec `json:"virtualMachineImage"` - ClusterVirtualMachineImage *ClusterImageDeviceSpec `json:"clusterVirtualMachineImage"` - VirtualMachineDisk *DiskDeviceSpec `json:"virtualMachineDisk"` - Hotpluggable bool `json:"hotpluggable"` - Target string `json:"target"` - Size string `json:"size"` +type BlockDeviceStatusRef struct { + Kind BlockDeviceKind `json:"kind"` + Name string `json:"name"` + Hotpluggable bool `json:"hotpluggable"` + Target string `json:"target"` + Size string `json:"size"` } -type BlockDeviceType string +type BlockDeviceKind string const ( - ImageDevice BlockDeviceType = "VirtualMachineImage" - ClusterImageDevice BlockDeviceType = "ClusterVirtualMachineImage" - DiskDevice BlockDeviceType = "VirtualMachineDisk" + ClusterImageDevice BlockDeviceKind = "ClusterVirtualImage" + ImageDevice BlockDeviceKind = "VirtualImage" + DiskDevice BlockDeviceKind = "VirtualDisk" ) - -type ClusterImageDeviceSpec struct { - Name string `json:"name"` -} - -type ImageDeviceSpec struct { - Name string `json:"name"` -} - -type DiskDeviceSpec struct { - Name string `json:"name"` -} diff --git a/api/core/v1alpha2/cluster_virtual_image.go b/api/core/v1alpha2/cluster_virtual_image.go new file mode 100644 index 000000000..c0c4a28b3 --- /dev/null +++ b/api/core/v1alpha2/cluster_virtual_image.go @@ -0,0 +1,64 @@ +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + ClusterVirtualImageKind = "ClusterVirtualImage" + ClusterVirtualImageResource = "clustervirtualimages" +) + +// +genclient:nonNamespaced + +// ClusterVirtualImage is a cluster wide available image for virtual machines. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ClusterVirtualImage struct { + metav1.TypeMeta `json:",inline"` + + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ClusterVirtualImageSpec `json:"spec"` + + Status ClusterVirtualImageStatus `json:"status,omitempty"` +} + +// ClusterVirtualImageList provides the needed parameters +// to do request a list of ClusterVirtualImages from the system. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ClusterVirtualImageList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of CDIs + Items []ClusterVirtualImage `json:"items"` +} + +type ClusterVirtualImageSpec struct { + DataSource ClusterVirtualImageDataSource `json:"dataSource"` +} + +type ClusterVirtualImageDataSource struct { + Type DataSourceType `json:"type,omitempty"` + HTTP *DataSourceHTTP `json:"http,omitempty"` + ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` + ObjectRef *ClusterVirtualImageObjectRef `json:"objectRef,omitempty"` +} + +type ClusterVirtualImageObjectRef struct { + Kind ClusterVirtualImageObjectRefKind `json:"kind,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` +} + +type ClusterVirtualImageObjectRefKind string + +const ( + ClusterVirtualImageObjectRefKindVirtualImage ClusterVirtualImageObjectRefKind = "VirtualImage" + ClusterVirtualImageObjectRefKindClusterVirtualImage ClusterVirtualImageObjectRefKind = "ClusterVirtualImage" +) + +type ClusterVirtualImageStatus struct { + ImageStatus `json:",inline"` +} diff --git a/api/core/v1alpha2/cluster_virtual_machine_image.go b/api/core/v1alpha2/cluster_virtual_machine_image.go deleted file mode 100644 index f848e29d7..000000000 --- a/api/core/v1alpha2/cluster_virtual_machine_image.go +++ /dev/null @@ -1,52 +0,0 @@ -package v1alpha2 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - CVMIKind = "ClusterVirtualMachineImage" - CVMIResource = "clustervirtualmachineimages" -) - -// +genclient:nonNamespaced - -// ClusterVirtualMachineImage is a cluster wide available image for virtual machines. -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type ClusterVirtualMachineImage struct { - metav1.TypeMeta `json:",inline"` - - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ClusterVirtualMachineImageSpec `json:"spec"` - - Status ClusterVirtualMachineImageStatus `json:"status,omitempty"` -} - -// ClusterVirtualMachineImageList provides the needed parameters -// to do request a list of ClusterVirtualMachineImages from the system. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type ClusterVirtualMachineImageList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata"` - - // Items provides a list of CDIs - Items []ClusterVirtualMachineImage `json:"items"` -} - -type ClusterVirtualMachineImageSpec struct { - DataSource CVMIDataSource `json:"dataSource"` -} - -type CVMIDataSource struct { - Type DataSourceType `json:"type,omitempty"` - HTTP *DataSourceHTTP `json:"http,omitempty"` - ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` - VirtualMachineImage *DataSourceNameNamespacedRef `json:"virtualMachineImage,omitempty"` - ClusterVirtualMachineImage *DataSourceNamedRef `json:"clusterVirtualMachineImage,omitempty"` -} - -type ClusterVirtualMachineImageStatus struct { - ImageStatus `json:",inline"` -} diff --git a/api/core/v1alpha2/data_source.go b/api/core/v1alpha2/data_source.go index 2644d1b85..71e30af94 100644 --- a/api/core/v1alpha2/data_source.go +++ b/api/core/v1alpha2/data_source.go @@ -1,14 +1,5 @@ package v1alpha2 -type DataSourceNamedRef struct { - Name string `json:"name"` -} - -type DataSourceNameNamespacedRef struct { - Name string `json:"name"` - Namespace string `json:"namespace"` -} - type DataSourceHTTP struct { URL string `json:"url"` CABundle []byte `json:"caBundle"` @@ -21,10 +12,6 @@ type DataSourceContainerRegistry struct { CABundle []byte `json:"caBundle"` } -type DataSourceClusterVirtualMachineImage struct { - Name string `json:"name"` -} - type ImagePullSecret struct { Name string `json:"name"` Namespace string `json:"namespace"` @@ -38,12 +25,10 @@ type Checksum struct { type DataSourceType string const ( - DataSourceTypeHTTP DataSourceType = "HTTP" - DataSourceTypeContainerImage DataSourceType = "ContainerImage" - DataSourceTypeVirtualMachineImage DataSourceType = "VirtualMachineImage" - DataSourceTypeClusterVirtualMachineImage DataSourceType = "ClusterVirtualMachineImage" - DataSourceTypeVirtualMachineDisk DataSourceType = "VirtualMachineDisk" - DataSourceTypeVirtualMachineDiskSnapshot DataSourceType = "VirtualMachineDiskSnapshot" - DataSourceTypePersistentVolumeClaim DataSourceType = "PersistentVolumeClaim" - DataSourceTypeUpload DataSourceType = "Upload" + DataSourceTypeHTTP DataSourceType = "HTTP" + DataSourceTypeContainerImage DataSourceType = "ContainerImage" + DataSourceTypeObjectRef DataSourceType = "ObjectRef" + DataSourceTypeUpload DataSourceType = "Upload" + DataSourceTypeVirtualDiskSnapshot DataSourceType = "VirtualDiskSnapshot" + DataSourceTypePersistentVolumeClaim DataSourceType = "PersistentVolumeClaim" ) diff --git a/api/core/v1alpha2/finalizers.go b/api/core/v1alpha2/finalizers.go index 9b53c770d..ec3f278c2 100644 --- a/api/core/v1alpha2/finalizers.go +++ b/api/core/v1alpha2/finalizers.go @@ -9,16 +9,16 @@ const ( FinalizerPVCProtection = "virtualization.deckhouse.io/pvc-protection" FinalizerPVProtection = "virtualization.deckhouse.io/pv-protection" - FinalizerCVMIProtection = "virtualization.deckhouse.io/cvmi-protection" - FinalizerVMIProtection = "virtualization.deckhouse.io/vmi-protection" - FinalizerVMDProtection = "virtualization.deckhouse.io/vmd-protection" + FinalizerCVMIProtection = "virtualization.deckhouse.io/cvi-protection" + FinalizerVMIProtection = "virtualization.deckhouse.io/vi-protection" + FinalizerVMDProtection = "virtualization.deckhouse.io/vd-protection" FinalizerKVVMProtection = "virtualization.deckhouse.io/kvvm-protection" FinalizerVMOPProtection = "virtualization.deckhouse.io/vmop-protection" FinalizerVMCPUProtection = "virtualization.deckhouse.io/vmcpu-protection" - FinalizerCVMICleanup = "virtualization.deckhouse.io/cvmi-cleanup" - FinalizerVMICleanup = "virtualization.deckhouse.io/vmi-cleanup" - FinalizerVMDCleanup = "virtualization.deckhouse.io/vmd-cleanup" + FinalizerCVMICleanup = "virtualization.deckhouse.io/cvi-cleanup" + FinalizerVMICleanup = "virtualization.deckhouse.io/vi-cleanup" + FinalizerVMDCleanup = "virtualization.deckhouse.io/vd-cleanup" FinalizerVMCleanup = "virtualization.deckhouse.io/vm-cleanup" FinalizerIPAddressClaimCleanup = "virtualization.deckhouse.io/vmip-cleanup" FinalizerIPAddressLeaseCleanup = "virtualization.deckhouse.io/vmipl-cleanup" diff --git a/api/core/v1alpha2/image_status.go b/api/core/v1alpha2/image_status.go index 0f4e84e37..6619490c0 100644 --- a/api/core/v1alpha2/image_status.go +++ b/api/core/v1alpha2/image_status.go @@ -17,7 +17,7 @@ type ImageStatus struct { DownloadSpeed ImageStatusSpeed `json:"downloadSpeed"` Size ImageStatusSize `json:"size"` Format string `json:"format"` - // FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName + // FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim Capacity string `json:"capacity,omitempty"` CDROM bool `json:"cdrom"` Target ImageStatusTarget `json:"target"` @@ -44,6 +44,6 @@ type ImageStatusSize struct { type ImageStatusTarget struct { RegistryURL string `json:"registryURL"` - // FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName - PersistentVolumeClaimName string `json:"persistentVolumeClaimName,omitempty"` + // FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim + PersistentVolumeClaim string `json:"persistentVolumeClaimName,omitempty"` } diff --git a/api/core/v1alpha2/register.go b/api/core/v1alpha2/register.go index fa449084f..0f2d08079 100644 --- a/api/core/v1alpha2/register.go +++ b/api/core/v1alpha2/register.go @@ -13,14 +13,14 @@ const Version = "v1alpha2" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: core.GroupName, Version: Version} -// ClusterVirtualMachineImageGVK is group version kind for ClusterVirtualMachineImage -var ClusterVirtualMachineImageGVK = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: CVMIKind} +// ClusterVirtualImageGVK is group version kind for ClusterVirtualImage +var ClusterVirtualImageGVK = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: ClusterVirtualImageKind} -// VirtualMachineImageGVK is group version kind for VirtualMachineImage -var VirtualMachineImageGVK = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: VMIKind} +// VirtualImageGVK is group version kind for VirtualImage +var VirtualImageGVK = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: VirtualImageKind} -// VirtualMachineDiskGVK is group version kind for VirtualMachineDisk -var VirtualMachineDiskGVK = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: VMDKind} +// VirtualDiskGVK is group version kind for VirtualDisk +var VirtualDiskGVK = schema.GroupVersionKind{Group: SchemeGroupVersion.Group, Version: SchemeGroupVersion.Version, Kind: VirtualDiskKind} // Kind takes an unqualified kind and returns back a Group qualified GroupKind func Kind(kind string) schema.GroupKind { @@ -46,12 +46,12 @@ var ( // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &ClusterVirtualMachineImage{}, - &ClusterVirtualMachineImageList{}, - &VirtualMachineImage{}, - &VirtualMachineImageList{}, - &VirtualMachineDisk{}, - &VirtualMachineDiskList{}, + &ClusterVirtualImage{}, + &ClusterVirtualImageList{}, + &VirtualImage{}, + &VirtualImageList{}, + &VirtualDisk{}, + &VirtualDiskList{}, &VirtualMachine{}, &VirtualMachineList{}, &VirtualMachineBlockDeviceAttachment{}, diff --git a/api/core/v1alpha2/virtual_disk.go b/api/core/v1alpha2/virtual_disk.go new file mode 100644 index 000000000..b897c8b27 --- /dev/null +++ b/api/core/v1alpha2/virtual_disk.go @@ -0,0 +1,94 @@ +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + VirtualDiskKind = "VirtualDisk" + VirtualDiskResource = "virtualdisks" +) + +// VirtualDisk is a disk ready to be bound by a VM +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualDisk struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VirtualDiskSpec `json:"spec"` + Status VirtualDiskStatus `json:"status,omitempty"` +} + +type VirtualDiskSpec struct { + DataSource *VirtualDiskDataSource `json:"dataSource,omitempty"` + PersistentVolumeClaim VirtualDiskPersistentVolumeClaim `json:"persistentVolumeClaim"` +} + +type VirtualDiskStatus struct { + ImportDuration string `json:"importDuration,omitempty"` + DownloadSpeed VirtualDiskDownloadSpeed `json:"downloadSpeed"` + Capacity string `json:"capacity,omitempty"` + Target DiskTarget `json:"target"` + Progress string `json:"progress,omitempty"` + UploadCommand string `json:"uploadCommand,omitempty"` + Phase DiskPhase `json:"phase"` + FailureReason string `json:"failureReason"` + FailureMessage string `json:"failureMessage"` +} + +type VirtualDiskDataSource struct { + Type DataSourceType `json:"type,omitempty"` + HTTP *DataSourceHTTP `json:"http,omitempty"` + ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` + ObjectRef *VirtualDiskObjectRef `json:"objectRef,omitempty"` +} + +type VirtualDiskObjectRef struct { + Kind VirtualDiskObjectRefKind `json:"kind,omitempty"` + Name string `json:"name,omitempty"` +} + +type VirtualDiskObjectRefKind string + +const ( + VirtualDiskObjectRefKindVirtualImage VirtualDiskObjectRefKind = "VirtualImage" + VirtualDiskObjectRefKindClusterVirtualImage VirtualDiskObjectRefKind = "ClusterVirtualImage" +) + +type VirtualDiskDownloadSpeed struct { + Avg string `json:"avg,omitempty"` + AvgBytes string `json:"avgBytes,omitempty"` + Current string `json:"current,omitempty"` + CurrentBytes string `json:"currentBytes,omitempty"` +} + +type DiskTarget struct { + PersistentVolumeClaim string `json:"persistentVolumeClaim"` +} + +type VirtualDiskPersistentVolumeClaim struct { + StorageClass *string `json:"storageClass,omitempty"` + Size *resource.Quantity `json:"size,omitempty"` +} + +// VirtualDiskList contains a list of VirtualDisk +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualDiskList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []VirtualDisk `json:"items"` +} + +type DiskPhase string + +const ( + DiskPending DiskPhase = "Pending" + DiskWaitForUserUpload DiskPhase = "WaitForUserUpload" + DiskProvisioning DiskPhase = "Provisioning" + DiskReady DiskPhase = "Ready" + DiskFailed DiskPhase = "Failed" + DiskPVCLost DiskPhase = "PVCLost" + DiskUnknown DiskPhase = "Unknown" +) diff --git a/api/core/v1alpha2/virtual_image.go b/api/core/v1alpha2/virtual_image.go new file mode 100644 index 000000000..b484f176c --- /dev/null +++ b/api/core/v1alpha2/virtual_image.go @@ -0,0 +1,74 @@ +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + VirtualImageKind = "VirtualImage" + VirtualImageResource = "virtualimages" +) + +// VirtualImage is an image for virtual machines available in the particular namespace. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualImage struct { + metav1.TypeMeta `json:",inline"` + + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VirtualImageSpec `json:"spec"` + + Status VirtualImageStatus `json:"status,omitempty"` +} + +// VirtualImageList provides the needed parameters +// to do request a list of VirtualImages from the system. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VirtualImageList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items provides a list of CDIs + Items []VirtualImage `json:"items"` +} + +type VirtualImageSpec struct { + Storage StorageType `json:"storage"` + PersistentVolumeClaim VirtualImagePersistentVolumeClaim `json:"persistentVolumeClaim"` + DataSource VirtualImageDataSource `json:"dataSource"` +} + +type VirtualImageStatus struct { + ImageStatus `json:",inline"` +} + +type VirtualImageDataSource struct { + Type DataSourceType `json:"type,omitempty"` + HTTP *DataSourceHTTP `json:"http,omitempty"` + ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` + ObjectRef *VirtualImageObjectRef `json:"objectRef,omitempty"` +} + +type VirtualImageObjectRef struct { + Kind VirtualImageObjectRefKind `json:"kind,omitempty"` + Name string `json:"name,omitempty"` +} + +type VirtualImageObjectRefKind string + +const ( + VirtualImageObjectRefKindVirtualImage VirtualImageObjectRefKind = "VirtualImage" + VirtualImageObjectRefKindClusterVirtualImage VirtualImageObjectRefKind = "ClusterVirtualImage" +) + +type StorageType string + +const ( + StorageContainerRegistry StorageType = "ContainerRegistry" + StorageKubernetes StorageType = "Kubernetes" +) + +type VirtualImagePersistentVolumeClaim struct { + StorageClass *string `json:"storageClass,omitempty"` +} diff --git a/api/core/v1alpha2/virtual_machine.go b/api/core/v1alpha2/virtual_machine.go index d91bf803a..106966f76 100644 --- a/api/core/v1alpha2/virtual_machine.go +++ b/api/core/v1alpha2/virtual_machine.go @@ -8,8 +8,8 @@ import ( ) const ( - VMKind = "VirtualMachine" - VMResource = "virtualmachines" + VirtualMachineKind = "VirtualMachine" + VirtualMachineResource = "virtualmachines" ) // VirtualMachine specifies configuration of the virtual machine. @@ -27,9 +27,9 @@ type VirtualMachineSpec struct { // RunPolicy is a power-on behaviour of the VM. RunPolicy RunPolicy `json:"runPolicy"` - // VirtualMachineIPAddressClaimName specifies a name for the associated - // `VirtualMahcineIPAddressClaim` resource. Defaults to `{vm name}`. - VirtualMachineIPAddressClaimName string `json:"virtualMachineIPAddressClaimName,omitempty"` + // VirtualMachineIPAddressClaim specifies a name for the associated + // `VirtualMachineIPAddressClaim` resource. Defaults to `{vm name}`. + VirtualMachineIPAddressClaim string `json:"virtualMachineIPAddressClaim,omitempty"` // TopologySpreadConstraints specifies how to spread matching pods among the given topology. TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` @@ -57,12 +57,12 @@ type VirtualMachineSpec struct { // Default value is true, so omitempty is not specified. EnableParavirtualization bool `json:"enableParavirtualization"` - OsType OsType `json:"osType,omitempty"` - Bootloader BootloaderType `json:"bootloader,omitempty"` - CPU CPUSpec `json:"cpu"` - Memory MemorySpec `json:"memory"` - BlockDevices []BlockDeviceSpec `json:"blockDevices"` - Provisioning *Provisioning `json:"provisioning"` + OsType OsType `json:"osType,omitempty"` + Bootloader BootloaderType `json:"bootloader,omitempty"` + CPU CPUSpec `json:"cpu"` + Memory MemorySpec `json:"memory"` + BlockDeviceRefs []BlockDeviceSpecRef `json:"blockDeviceRefs"` + Provisioning *Provisioning `json:"provisioning"` } type RunPolicy string @@ -91,9 +91,9 @@ const ( ) type CPUSpec struct { - ModelName string `json:"modelName"` - Cores int `json:"cores"` - CoreFraction string `json:"coreFraction"` + VirtualMachineCPUModel string `json:"virtualMachineCPUModel"` + Cores int `json:"cores"` + CoreFraction string `json:"coreFraction"` } type MemorySpec struct { @@ -113,20 +113,42 @@ type Disruptions struct { } type Provisioning struct { - Type ProvisioningType `json:"type"` - SysprepSecretRef *corev1.LocalObjectReference `json:"sysprepSecretRef,omitempty"` - UserData string `json:"userData,omitempty"` - UserDataSecretRef *corev1.LocalObjectReference `json:"userDataSecretRef,omitempty"` + Type ProvisioningType `json:"type"` + UserData string `json:"userData,omitempty"` + UserDataRef *UserDataRef `json:"userDataRef,omitempty"` + SysprepRef *SysprepRef `json:"sysprepRef,omitempty"` } +type UserDataRef struct { + Kind UserDataRefKind `json:"kind"` + Name string `json:"name"` +} + +type UserDataRefKind string + +const ( + UserDataRefKindSecret UserDataRefKind = "Secret" +) + +type SysprepRef struct { + Kind SysprepRefKind `json:"kind"` + Name string `json:"name"` +} + +type SysprepRefKind string + +const ( + SysprepRefKindSecret SysprepRefKind = "Secret" +) + type VirtualMachineStatus struct { - Phase MachinePhase `json:"phase"` - NodeName string `json:"nodeName"` - IPAddressClaim string `json:"ipAddressClaim"` - IPAddress string `json:"ipAddress"` - BlockDevicesAttached []BlockDeviceStatus `json:"blockDevicesAttached"` - GuestOSInfo virtv1.VirtualMachineInstanceGuestOSInfo `json:"guestOSInfo"` - Message string `json:"message"` + Phase MachinePhase `json:"phase"` + Node string `json:"node"` + VirtualMachineIPAddressClaim string `json:"virtualMachineIPAddressClaim"` + IPAddress string `json:"ipAddress"` + BlockDeviceRefs []BlockDeviceStatusRef `json:"blockDeviceRefs"` + GuestOSInfo virtv1.VirtualMachineInstanceGuestOSInfo `json:"guestOSInfo"` + Message string `json:"message"` // RestartAwaitingChanges holds operations to be manually approved // before applying to the virtual machine spec. @@ -170,7 +192,7 @@ type VirtualMachineList struct { type ProvisioningType string const ( - ProvisioningTypeSysprepSecret ProvisioningType = "SysprepSecret" - ProvisioningTypeUserData ProvisioningType = "UserData" - ProvisioningTypeUserDataSecret ProvisioningType = "UserDataSecret" + ProvisioningTypeUserData ProvisioningType = "UserData" + ProvisioningTypeUserDataRef ProvisioningType = "UserDataRef" + ProvisioningTypeSysprepRef ProvisioningType = "SysprepRef" ) diff --git a/api/core/v1alpha2/virtual_machine_block_disk_attachment.go b/api/core/v1alpha2/virtual_machine_block_disk_attachment.go index b019e732c..9adc6c861 100644 --- a/api/core/v1alpha2/virtual_machine_block_disk_attachment.go +++ b/api/core/v1alpha2/virtual_machine_block_disk_attachment.go @@ -29,25 +29,27 @@ type VirtualMachineBlockDeviceAttachmentList struct { } type VirtualMachineBlockDeviceAttachmentSpec struct { - VMName string `json:"virtualMachineName"` - BlockDevice BlockDeviceAttachmentBlockDevice `json:"blockDevice"` + VirtualMachine string `json:"virtualMachine"` + BlockDeviceRef VMBDAObjectRef `json:"blockDeviceRef"` } -type BlockDeviceAttachmentBlockDevice struct { - Type BlockDeviceAttachmentType `json:"type"` - VirtualMachineDisk *BlockDeviceAttachmentVirtualMachineDisk `json:"virtualMachineDisk"` +type VMBDAObjectRef struct { + Kind VMBDAObjectRefKind `json:"kind,omitempty"` + Name string `json:"name,omitempty"` } -type BlockDeviceAttachmentType string +type VMBDAObjectRefKind string -const BlockDeviceAttachmentTypeVirtualMachineDisk BlockDeviceAttachmentType = "VirtualMachineDisk" +const ( + VMBDAObjectRefKindVirtualDisk VMBDAObjectRefKind = "VirtualDisk" +) -type BlockDeviceAttachmentVirtualMachineDisk struct { - Name string `json:"name"` -} +type VirtualMachineBlockDeviceAttachmentObjectRefKind string + +const BlockDeviceAttachmentTypeVirtualDisk VirtualMachineBlockDeviceAttachmentObjectRefKind = "VirtualDisk" type VirtualMachineBlockDeviceAttachmentStatus struct { - VMName string `json:"virtualMachineName,omitempty"` + VirtualMachine string `json:"virtualMachine,omitempty"` Phase BlockDeviceAttachmentPhase `json:"phase,omitempty"` FailureReason string `json:"failureReason,omitempty"` FailureMessage string `json:"failureMessage,omitempty"` diff --git a/api/core/v1alpha2/virtual_machine_disk.go b/api/core/v1alpha2/virtual_machine_disk.go deleted file mode 100644 index f7a204a16..000000000 --- a/api/core/v1alpha2/virtual_machine_disk.go +++ /dev/null @@ -1,83 +0,0 @@ -package v1alpha2 - -import ( - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - VMDKind = "VirtualMachineDisk" - VMDResource = "virtualmachinedisks" -) - -// VirtualMachineDisk is a disk ready to be bound by a VM -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type VirtualMachineDisk struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec VirtualMachineDiskSpec `json:"spec"` - Status VirtualMachineDiskStatus `json:"status,omitempty"` -} - -type VirtualMachineDiskSpec struct { - DataSource *VMDDataSource `json:"dataSource,omitempty"` - PersistentVolumeClaim VMDPersistentVolumeClaim `json:"persistentVolumeClaim"` -} - -type VirtualMachineDiskStatus struct { - ImportDuration string `json:"importDuration,omitempty"` - DownloadSpeed VMDDownloadSpeed `json:"downloadSpeed"` - Capacity string `json:"capacity,omitempty"` - Target DiskTarget `json:"target"` - Progress string `json:"progress,omitempty"` - UploadCommand string `json:"uploadCommand,omitempty"` - Phase DiskPhase `json:"phase"` - FailureReason string `json:"failureReason"` - FailureMessage string `json:"failureMessage"` -} - -type VMDDataSource struct { - Type DataSourceType `json:"type,omitempty"` - HTTP *DataSourceHTTP `json:"http,omitempty"` - ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` - VirtualMachineImage *DataSourceNamedRef `json:"virtualMachineImage,omitempty"` - ClusterVirtualMachineImage *DataSourceNamedRef `json:"clusterVirtualMachineImage,omitempty"` -} - -type VMDDownloadSpeed struct { - Avg string `json:"avg,omitempty"` - AvgBytes string `json:"avgBytes,omitempty"` - Current string `json:"current,omitempty"` - CurrentBytes string `json:"currentBytes,omitempty"` -} - -type DiskTarget struct { - PersistentVolumeClaimName string `json:"persistentVolumeClaimName"` -} - -type VMDPersistentVolumeClaim struct { - StorageClassName *string `json:"storageClassName,omitempty"` - Size *resource.Quantity `json:"size,omitempty"` -} - -// VirtualMachineDiskList contains a list of VirtualMachineDisk -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type VirtualMachineDiskList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata"` - Items []VirtualMachineDisk `json:"items"` -} - -type DiskPhase string - -const ( - DiskPending DiskPhase = "Pending" - DiskWaitForUserUpload DiskPhase = "WaitForUserUpload" - DiskProvisioning DiskPhase = "Provisioning" - DiskReady DiskPhase = "Ready" - DiskFailed DiskPhase = "Failed" - DiskPVCLost DiskPhase = "PVCLost" - DiskUnknown DiskPhase = "Unknown" -) diff --git a/api/core/v1alpha2/virtual_machine_image.go b/api/core/v1alpha2/virtual_machine_image.go deleted file mode 100644 index d1adaa3af..000000000 --- a/api/core/v1alpha2/virtual_machine_image.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1alpha2 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - VMIKind = "VirtualMachineImage" - VMIResource = "virtualmachineimages" -) - -// VirtualMachineImage is an image for virtual machines available in the particular namespace. -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type VirtualMachineImage struct { - metav1.TypeMeta `json:",inline"` - - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec VirtualMachineImageSpec `json:"spec"` - - Status VirtualMachineImageStatus `json:"status,omitempty"` -} - -// VirtualMachineImageList provides the needed parameters -// to do request a list of ClusterVirtualMachineImages from the system. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type VirtualMachineImageList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata"` - - // Items provides a list of CDIs - Items []VirtualMachineImage `json:"items"` -} - -type VirtualMachineImageSpec struct { - Storage StorageType `json:"storage"` - PersistentVolumeClaim VMIPersistentVolumeClaim `json:"persistentVolumeClaim"` - DataSource VMIDataSource `json:"dataSource"` -} - -type VirtualMachineImageStatus struct { - ImageStatus `json:",inline"` -} - -type VMIDataSource struct { - Type DataSourceType `json:"type,omitempty"` - HTTP *DataSourceHTTP `json:"http,omitempty"` - ContainerImage *DataSourceContainerRegistry `json:"containerImage,omitempty"` - VirtualMachineImage *DataSourceNamedRef `json:"virtualMachineImage,omitempty"` - ClusterVirtualMachineImage *DataSourceNamedRef `json:"clusterVirtualMachineImage,omitempty"` -} - -type StorageType string - -const ( - StorageContainerRegistry StorageType = "ContainerRegistry" - StorageKubernetes StorageType = "Kubernetes" -) - -type VMIPersistentVolumeClaim struct { - StorageClassName *string `json:"storageClassName,omitempty"` -} diff --git a/api/core/v1alpha2/virtual_machine_ip_address_claim.go b/api/core/v1alpha2/virtual_machine_ip_address_claim.go index 90d493bd6..be9a31f80 100644 --- a/api/core/v1alpha2/virtual_machine_ip_address_claim.go +++ b/api/core/v1alpha2/virtual_machine_ip_address_claim.go @@ -26,7 +26,7 @@ type VirtualMachineIPAddressClaimList struct { // VirtualMachineIPAddressClaimSpec is the desired state of `VirtualMachineIPAddressClaim`. type VirtualMachineIPAddressClaimSpec struct { // The issued `VirtualMachineIPAddressLease`, managed automatically. - LeaseName string `json:"leaseName"` + VirtualMachineIPAddressLease string `json:"virtualMachineIPAddressLease"` // The requested IP address. If omitted the next available IP address will be assigned. Address string `json:"address"` // Determines the behavior of VirtualMachineIPAddressLease upon VirtualMachineIPAddressClaim deletion. @@ -36,11 +36,11 @@ type VirtualMachineIPAddressClaimSpec struct { // VirtualMachineIPAddressClaimStatus is the observed state of `VirtualMachineIPAddressClaim`. type VirtualMachineIPAddressClaimStatus struct { // Represents the virtual machine that currently uses this IP address. - VMName string `json:"virtualMachineName,omitempty"` + VirtualMachine string `json:"virtualMachine,omitempty"` // Assigned IP address. Address string `json:"address,omitempty"` // The issued `VirtualMachineIPAddressLease`, managed automatically. - LeaseName string `json:"leaseName,omitempty"` + Lease string `json:"virtualMachineIPAddressLease,omitempty"` // Represents the current state of IP address claim. Phase VirtualMachineIPAddressClaimPhase `json:"phase,omitempty"` // Detailed description of the error. diff --git a/api/core/v1alpha2/virtual_machine_operation.go b/api/core/v1alpha2/virtual_machine_operation.go index ae08ce021..677133dae 100644 --- a/api/core/v1alpha2/virtual_machine_operation.go +++ b/api/core/v1alpha2/virtual_machine_operation.go @@ -19,9 +19,9 @@ type VirtualMachineOperation struct { } type VirtualMachineOperationSpec struct { - Type VMOPOperation `json:"type"` - VirtualMachineName string `json:"virtualMachineName"` - Force bool `json:"force,omitempty"` + Type VMOPOperation `json:"type"` + VirtualMachine string `json:"virtualMachine"` + Force bool `json:"force,omitempty"` } type VirtualMachineOperationStatus struct { diff --git a/api/core/v1alpha2/zz_generated.deepcopy.go b/api/core/v1alpha2/zz_generated.deepcopy.go index b9f83cac6..fb1ae21e0 100644 --- a/api/core/v1alpha2/zz_generated.deepcopy.go +++ b/api/core/v1alpha2/zz_generated.deepcopy.go @@ -28,122 +28,99 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BlockDeviceAttachmentBlockDevice) DeepCopyInto(out *BlockDeviceAttachmentBlockDevice) { +func (in *BlockDeviceSpecRef) DeepCopyInto(out *BlockDeviceSpecRef) { *out = *in - if in.VirtualMachineDisk != nil { - in, out := &in.VirtualMachineDisk, &out.VirtualMachineDisk - *out = new(BlockDeviceAttachmentVirtualMachineDisk) - **out = **in - } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceAttachmentBlockDevice. -func (in *BlockDeviceAttachmentBlockDevice) DeepCopy() *BlockDeviceAttachmentBlockDevice { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceSpecRef. +func (in *BlockDeviceSpecRef) DeepCopy() *BlockDeviceSpecRef { if in == nil { return nil } - out := new(BlockDeviceAttachmentBlockDevice) + out := new(BlockDeviceSpecRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BlockDeviceAttachmentVirtualMachineDisk) DeepCopyInto(out *BlockDeviceAttachmentVirtualMachineDisk) { +func (in *BlockDeviceStatusRef) DeepCopyInto(out *BlockDeviceStatusRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceAttachmentVirtualMachineDisk. -func (in *BlockDeviceAttachmentVirtualMachineDisk) DeepCopy() *BlockDeviceAttachmentVirtualMachineDisk { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceStatusRef. +func (in *BlockDeviceStatusRef) DeepCopy() *BlockDeviceStatusRef { if in == nil { return nil } - out := new(BlockDeviceAttachmentVirtualMachineDisk) + out := new(BlockDeviceStatusRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BlockDeviceSpec) DeepCopyInto(out *BlockDeviceSpec) { +func (in *CPUSpec) DeepCopyInto(out *CPUSpec) { *out = *in - if in.VirtualMachineImage != nil { - in, out := &in.VirtualMachineImage, &out.VirtualMachineImage - *out = new(ImageDeviceSpec) - **out = **in - } - if in.ClusterVirtualMachineImage != nil { - in, out := &in.ClusterVirtualMachineImage, &out.ClusterVirtualMachineImage - *out = new(ClusterImageDeviceSpec) - **out = **in - } - if in.VirtualMachineDisk != nil { - in, out := &in.VirtualMachineDisk, &out.VirtualMachineDisk - *out = new(DiskDeviceSpec) - **out = **in - } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceSpec. -func (in *BlockDeviceSpec) DeepCopy() *BlockDeviceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPUSpec. +func (in *CPUSpec) DeepCopy() *CPUSpec { if in == nil { return nil } - out := new(BlockDeviceSpec) + out := new(CPUSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BlockDeviceStatus) DeepCopyInto(out *BlockDeviceStatus) { +func (in *Checksum) DeepCopyInto(out *Checksum) { *out = *in - if in.VirtualMachineImage != nil { - in, out := &in.VirtualMachineImage, &out.VirtualMachineImage - *out = new(ImageDeviceSpec) - **out = **in - } - if in.ClusterVirtualMachineImage != nil { - in, out := &in.ClusterVirtualMachineImage, &out.ClusterVirtualMachineImage - *out = new(ClusterImageDeviceSpec) - **out = **in - } - if in.VirtualMachineDisk != nil { - in, out := &in.VirtualMachineDisk, &out.VirtualMachineDisk - *out = new(DiskDeviceSpec) - **out = **in - } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceStatus. -func (in *BlockDeviceStatus) DeepCopy() *BlockDeviceStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Checksum. +func (in *Checksum) DeepCopy() *Checksum { if in == nil { return nil } - out := new(BlockDeviceStatus) + out := new(Checksum) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CPUSpec) DeepCopyInto(out *CPUSpec) { +func (in *ClusterVirtualImage) DeepCopyInto(out *ClusterVirtualImage) { *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPUSpec. -func (in *CPUSpec) DeepCopy() *CPUSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImage. +func (in *ClusterVirtualImage) DeepCopy() *ClusterVirtualImage { if in == nil { return nil } - out := new(CPUSpec) + out := new(ClusterVirtualImage) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterVirtualImage) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CVMIDataSource) DeepCopyInto(out *CVMIDataSource) { +func (in *ClusterVirtualImageDataSource) DeepCopyInto(out *ClusterVirtualImageDataSource) { *out = *in if in.HTTP != nil { in, out := &in.HTTP, &out.HTTP @@ -155,474 +132,611 @@ func (in *CVMIDataSource) DeepCopyInto(out *CVMIDataSource) { *out = new(DataSourceContainerRegistry) (*in).DeepCopyInto(*out) } - if in.VirtualMachineImage != nil { - in, out := &in.VirtualMachineImage, &out.VirtualMachineImage - *out = new(DataSourceNameNamespacedRef) - **out = **in - } - if in.ClusterVirtualMachineImage != nil { - in, out := &in.ClusterVirtualMachineImage, &out.ClusterVirtualMachineImage - *out = new(DataSourceNamedRef) + if in.ObjectRef != nil { + in, out := &in.ObjectRef, &out.ObjectRef + *out = new(ClusterVirtualImageObjectRef) **out = **in } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CVMIDataSource. -func (in *CVMIDataSource) DeepCopy() *CVMIDataSource { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageDataSource. +func (in *ClusterVirtualImageDataSource) DeepCopy() *ClusterVirtualImageDataSource { if in == nil { return nil } - out := new(CVMIDataSource) + out := new(ClusterVirtualImageDataSource) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Checksum) DeepCopyInto(out *Checksum) { +func (in *ClusterVirtualImageList) DeepCopyInto(out *ClusterVirtualImageList) { *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterVirtualImage, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Checksum. -func (in *Checksum) DeepCopy() *Checksum { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageList. +func (in *ClusterVirtualImageList) DeepCopy() *ClusterVirtualImageList { if in == nil { return nil } - out := new(Checksum) + out := new(ClusterVirtualImageList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterVirtualImageList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterImageDeviceSpec) DeepCopyInto(out *ClusterImageDeviceSpec) { +func (in *ClusterVirtualImageObjectRef) DeepCopyInto(out *ClusterVirtualImageObjectRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterImageDeviceSpec. -func (in *ClusterImageDeviceSpec) DeepCopy() *ClusterImageDeviceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageObjectRef. +func (in *ClusterVirtualImageObjectRef) DeepCopy() *ClusterVirtualImageObjectRef { if in == nil { return nil } - out := new(ClusterImageDeviceSpec) + out := new(ClusterVirtualImageObjectRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVirtualMachineImage) DeepCopyInto(out *ClusterVirtualMachineImage) { +func (in *ClusterVirtualImageSpec) DeepCopyInto(out *ClusterVirtualImageSpec) { *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status + in.DataSource.DeepCopyInto(&out.DataSource) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualMachineImage. -func (in *ClusterVirtualMachineImage) DeepCopy() *ClusterVirtualMachineImage { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageSpec. +func (in *ClusterVirtualImageSpec) DeepCopy() *ClusterVirtualImageSpec { if in == nil { return nil } - out := new(ClusterVirtualMachineImage) + out := new(ClusterVirtualImageSpec) in.DeepCopyInto(out) return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterVirtualMachineImage) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c +// 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 + out.ImageStatus = in.ImageStatus + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualImageStatus. +func (in *ClusterVirtualImageStatus) DeepCopy() *ClusterVirtualImageStatus { + if in == nil { + return nil } - return nil + out := new(ClusterVirtualImageStatus) + in.DeepCopyInto(out) + return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVirtualMachineImageList) DeepCopyInto(out *ClusterVirtualMachineImageList) { +func (in *DataSourceContainerRegistry) DeepCopyInto(out *DataSourceContainerRegistry) { *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ClusterVirtualMachineImage, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + 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 ClusterVirtualMachineImageList. -func (in *ClusterVirtualMachineImageList) DeepCopy() *ClusterVirtualMachineImageList { +// 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(ClusterVirtualMachineImageList) + out := new(DataSourceContainerRegistry) in.DeepCopyInto(out) return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterVirtualMachineImageList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c +// 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) } - return nil + if in.Checksum != nil { + in, out := &in.Checksum, &out.Checksum + *out = new(Checksum) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceHTTP. +func (in *DataSourceHTTP) DeepCopy() *DataSourceHTTP { + if in == nil { + return nil + } + out := new(DataSourceHTTP) + in.DeepCopyInto(out) + return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVirtualMachineImageSpec) DeepCopyInto(out *ClusterVirtualMachineImageSpec) { +func (in *DiskTarget) DeepCopyInto(out *DiskTarget) { *out = *in - in.DataSource.DeepCopyInto(&out.DataSource) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualMachineImageSpec. -func (in *ClusterVirtualMachineImageSpec) DeepCopy() *ClusterVirtualMachineImageSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskTarget. +func (in *DiskTarget) DeepCopy() *DiskTarget { if in == nil { return nil } - out := new(ClusterVirtualMachineImageSpec) + out := new(DiskTarget) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVirtualMachineImageStatus) DeepCopyInto(out *ClusterVirtualMachineImageStatus) { +func (in *Disruptions) DeepCopyInto(out *Disruptions) { *out = *in - out.ImageStatus = in.ImageStatus return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVirtualMachineImageStatus. -func (in *ClusterVirtualMachineImageStatus) DeepCopy() *ClusterVirtualMachineImageStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Disruptions. +func (in *Disruptions) DeepCopy() *Disruptions { if in == nil { return nil } - out := new(ClusterVirtualMachineImageStatus) + out := new(Disruptions) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataSourceClusterVirtualMachineImage) DeepCopyInto(out *DataSourceClusterVirtualMachineImage) { +func (in *ImagePullSecret) DeepCopyInto(out *ImagePullSecret) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceClusterVirtualMachineImage. -func (in *DataSourceClusterVirtualMachineImage) DeepCopy() *DataSourceClusterVirtualMachineImage { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullSecret. +func (in *ImagePullSecret) DeepCopy() *ImagePullSecret { if in == nil { return nil } - out := new(DataSourceClusterVirtualMachineImage) + out := new(ImagePullSecret) in.DeepCopyInto(out) 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) { +func (in *ImageStatus) DeepCopyInto(out *ImageStatus) { *out = *in - out.ImagePullSecret = in.ImagePullSecret - if in.CABundle != nil { - in, out := &in.CABundle, &out.CABundle - *out = make([]byte, len(*in)) - copy(*out, *in) - } + out.DownloadSpeed = in.DownloadSpeed + out.Size = in.Size + out.Target = in.Target return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceContainerRegistry. -func (in *DataSourceContainerRegistry) DeepCopy() *DataSourceContainerRegistry { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatus. +func (in *ImageStatus) DeepCopy() *ImageStatus { if in == nil { return nil } - out := new(DataSourceContainerRegistry) + out := new(ImageStatus) 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) { +func (in *ImageStatusSize) DeepCopyInto(out *ImageStatusSize) { *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 + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatusSize. +func (in *ImageStatusSize) DeepCopy() *ImageStatusSize { + if in == nil { + return nil } + out := new(ImageStatusSize) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageStatusSpeed) DeepCopyInto(out *ImageStatusSpeed) { + *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceHTTP. -func (in *DataSourceHTTP) DeepCopy() *DataSourceHTTP { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatusSpeed. +func (in *ImageStatusSpeed) DeepCopy() *ImageStatusSpeed { if in == nil { return nil } - out := new(DataSourceHTTP) + out := new(ImageStatusSpeed) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataSourceNameNamespacedRef) DeepCopyInto(out *DataSourceNameNamespacedRef) { +func (in *ImageStatusTarget) DeepCopyInto(out *ImageStatusTarget) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceNameNamespacedRef. -func (in *DataSourceNameNamespacedRef) DeepCopy() *DataSourceNameNamespacedRef { +// 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(DataSourceNameNamespacedRef) + 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 *DataSourceNamedRef) DeepCopyInto(out *DataSourceNamedRef) { +func (in *MemorySpec) DeepCopyInto(out *MemorySpec) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceNamedRef. -func (in *DataSourceNamedRef) DeepCopy() *DataSourceNamedRef { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemorySpec. +func (in *MemorySpec) DeepCopy() *MemorySpec { if in == nil { return nil } - out := new(DataSourceNamedRef) + out := new(MemorySpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DiskDeviceSpec) DeepCopyInto(out *DiskDeviceSpec) { +func (in *Provisioning) DeepCopyInto(out *Provisioning) { *out = *in + if in.UserDataRef != nil { + in, out := &in.UserDataRef, &out.UserDataRef + *out = new(UserDataRef) + **out = **in + } + if in.SysprepRef != nil { + in, out := &in.SysprepRef, &out.SysprepRef + *out = new(SysprepRef) + **out = **in + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskDeviceSpec. -func (in *DiskDeviceSpec) DeepCopy() *DiskDeviceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Provisioning. +func (in *Provisioning) DeepCopy() *Provisioning { if in == nil { return nil } - out := new(DiskDeviceSpec) + out := new(Provisioning) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DiskTarget) DeepCopyInto(out *DiskTarget) { +func (in *SysprepRef) DeepCopyInto(out *SysprepRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskTarget. -func (in *DiskTarget) DeepCopy() *DiskTarget { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SysprepRef. +func (in *SysprepRef) DeepCopy() *SysprepRef { if in == nil { return nil } - out := new(DiskTarget) + out := new(SysprepRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Disruptions) DeepCopyInto(out *Disruptions) { +func (in *UserDataRef) DeepCopyInto(out *UserDataRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Disruptions. -func (in *Disruptions) DeepCopy() *Disruptions { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserDataRef. +func (in *UserDataRef) DeepCopy() *UserDataRef { if in == nil { return nil } - out := new(Disruptions) + out := new(UserDataRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ImageDeviceSpec) DeepCopyInto(out *ImageDeviceSpec) { +func (in *VMAffinity) DeepCopyInto(out *VMAffinity) { *out = *in + if in.NodeAffinity != nil { + in, out := &in.NodeAffinity, &out.NodeAffinity + *out = new(v1.NodeAffinity) + (*in).DeepCopyInto(*out) + } + if in.VirtualMachineAndPodAffinity != nil { + in, out := &in.VirtualMachineAndPodAffinity, &out.VirtualMachineAndPodAffinity + *out = new(VirtualMachineAndPodAffinity) + (*in).DeepCopyInto(*out) + } + if in.VirtualMachineAndPodAntiAffinity != nil { + in, out := &in.VirtualMachineAndPodAntiAffinity, &out.VirtualMachineAndPodAntiAffinity + *out = new(VirtualMachineAndPodAntiAffinity) + (*in).DeepCopyInto(*out) + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageDeviceSpec. -func (in *ImageDeviceSpec) DeepCopy() *ImageDeviceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMAffinity. +func (in *VMAffinity) DeepCopy() *VMAffinity { if in == nil { return nil } - out := new(ImageDeviceSpec) + out := new(VMAffinity) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ImagePullSecret) DeepCopyInto(out *ImagePullSecret) { +func (in *VMBDAObjectRef) DeepCopyInto(out *VMBDAObjectRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullSecret. -func (in *ImagePullSecret) DeepCopy() *ImagePullSecret { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMBDAObjectRef. +func (in *VMBDAObjectRef) DeepCopy() *VMBDAObjectRef { if in == nil { return nil } - out := new(ImagePullSecret) + out := new(VMBDAObjectRef) in.DeepCopyInto(out) return out } // 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 *VirtualDisk) DeepCopyInto(out *VirtualDisk) { *out = *in - out.DownloadSpeed = in.DownloadSpeed - out.Size = in.Size - out.Target = in.Target + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status 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 VirtualDisk. +func (in *VirtualDisk) DeepCopy() *VirtualDisk { if in == nil { return nil } - out := new(ImageStatus) + out := new(VirtualDisk) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualDisk) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ImageStatusSize) DeepCopyInto(out *ImageStatusSize) { +func (in *VirtualDiskDataSource) DeepCopyInto(out *VirtualDiskDataSource) { *out = *in + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(DataSourceHTTP) + (*in).DeepCopyInto(*out) + } + if in.ContainerImage != nil { + in, out := &in.ContainerImage, &out.ContainerImage + *out = new(DataSourceContainerRegistry) + (*in).DeepCopyInto(*out) + } + if in.ObjectRef != nil { + in, out := &in.ObjectRef, &out.ObjectRef + *out = new(VirtualDiskObjectRef) + **out = **in + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatusSize. -func (in *ImageStatusSize) DeepCopy() *ImageStatusSize { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskDataSource. +func (in *VirtualDiskDataSource) DeepCopy() *VirtualDiskDataSource { if in == nil { return nil } - out := new(ImageStatusSize) + out := new(VirtualDiskDataSource) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ImageStatusSpeed) DeepCopyInto(out *ImageStatusSpeed) { +func (in *VirtualDiskDownloadSpeed) DeepCopyInto(out *VirtualDiskDownloadSpeed) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatusSpeed. -func (in *ImageStatusSpeed) DeepCopy() *ImageStatusSpeed { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskDownloadSpeed. +func (in *VirtualDiskDownloadSpeed) DeepCopy() *VirtualDiskDownloadSpeed { if in == nil { return nil } - out := new(ImageStatusSpeed) + out := new(VirtualDiskDownloadSpeed) in.DeepCopyInto(out) 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) { +func (in *VirtualDiskList) DeepCopyInto(out *VirtualDiskList) { *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualDisk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatusTarget. -func (in *ImageStatusTarget) DeepCopy() *ImageStatusTarget { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskList. +func (in *VirtualDiskList) DeepCopy() *VirtualDiskList { if in == nil { return nil } - out := new(ImageStatusTarget) + out := new(VirtualDiskList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualDiskList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MemorySpec) DeepCopyInto(out *MemorySpec) { +func (in *VirtualDiskObjectRef) DeepCopyInto(out *VirtualDiskObjectRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemorySpec. -func (in *MemorySpec) DeepCopy() *MemorySpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskObjectRef. +func (in *VirtualDiskObjectRef) DeepCopy() *VirtualDiskObjectRef { if in == nil { return nil } - out := new(MemorySpec) + out := new(VirtualDiskObjectRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Provisioning) DeepCopyInto(out *Provisioning) { +func (in *VirtualDiskPersistentVolumeClaim) DeepCopyInto(out *VirtualDiskPersistentVolumeClaim) { *out = *in - if in.SysprepSecretRef != nil { - in, out := &in.SysprepSecretRef, &out.SysprepSecretRef - *out = new(v1.LocalObjectReference) + if in.StorageClass != nil { + in, out := &in.StorageClass, &out.StorageClass + *out = new(string) **out = **in } - if in.UserDataSecretRef != nil { - in, out := &in.UserDataSecretRef, &out.UserDataSecretRef - *out = new(v1.LocalObjectReference) - **out = **in + if in.Size != nil { + in, out := &in.Size, &out.Size + x := (*in).DeepCopy() + *out = &x + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskPersistentVolumeClaim. +func (in *VirtualDiskPersistentVolumeClaim) DeepCopy() *VirtualDiskPersistentVolumeClaim { + if in == nil { + return nil + } + out := new(VirtualDiskPersistentVolumeClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualDiskSpec) DeepCopyInto(out *VirtualDiskSpec) { + *out = *in + if in.DataSource != nil { + in, out := &in.DataSource, &out.DataSource + *out = new(VirtualDiskDataSource) + (*in).DeepCopyInto(*out) + } + in.PersistentVolumeClaim.DeepCopyInto(&out.PersistentVolumeClaim) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskSpec. +func (in *VirtualDiskSpec) DeepCopy() *VirtualDiskSpec { + if in == nil { + return nil } + out := new(VirtualDiskSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualDiskStatus) DeepCopyInto(out *VirtualDiskStatus) { + *out = *in + out.DownloadSpeed = in.DownloadSpeed + out.Target = in.Target return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Provisioning. -func (in *Provisioning) DeepCopy() *Provisioning { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualDiskStatus. +func (in *VirtualDiskStatus) DeepCopy() *VirtualDiskStatus { if in == nil { return nil } - out := new(Provisioning) + out := new(VirtualDiskStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VMAffinity) DeepCopyInto(out *VMAffinity) { +func (in *VirtualImage) DeepCopyInto(out *VirtualImage) { *out = *in - if in.NodeAffinity != nil { - in, out := &in.NodeAffinity, &out.NodeAffinity - *out = new(v1.NodeAffinity) - (*in).DeepCopyInto(*out) - } - if in.VirtualMachineAndPodAffinity != nil { - in, out := &in.VirtualMachineAndPodAffinity, &out.VirtualMachineAndPodAffinity - *out = new(VirtualMachineAndPodAffinity) - (*in).DeepCopyInto(*out) - } - if in.VirtualMachineAndPodAntiAffinity != nil { - in, out := &in.VirtualMachineAndPodAntiAffinity, &out.VirtualMachineAndPodAntiAffinity - *out = new(VirtualMachineAndPodAntiAffinity) - (*in).DeepCopyInto(*out) - } + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMAffinity. -func (in *VMAffinity) DeepCopy() *VMAffinity { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImage. +func (in *VirtualImage) DeepCopy() *VirtualImage { if in == nil { return nil } - out := new(VMAffinity) + out := new(VirtualImage) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualImage) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VMDDataSource) DeepCopyInto(out *VMDDataSource) { +func (in *VirtualImageDataSource) DeepCopyInto(out *VirtualImageDataSource) { *out = *in if in.HTTP != nil { in, out := &in.HTTP, &out.HTTP @@ -634,124 +748,125 @@ func (in *VMDDataSource) DeepCopyInto(out *VMDDataSource) { *out = new(DataSourceContainerRegistry) (*in).DeepCopyInto(*out) } - if in.VirtualMachineImage != nil { - in, out := &in.VirtualMachineImage, &out.VirtualMachineImage - *out = new(DataSourceNamedRef) + if in.ObjectRef != nil { + in, out := &in.ObjectRef, &out.ObjectRef + *out = new(VirtualImageObjectRef) **out = **in } - if in.ClusterVirtualMachineImage != nil { - in, out := &in.ClusterVirtualMachineImage, &out.ClusterVirtualMachineImage - *out = new(DataSourceNamedRef) - **out = **in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageDataSource. +func (in *VirtualImageDataSource) DeepCopy() *VirtualImageDataSource { + if in == nil { + return nil + } + out := new(VirtualImageDataSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualImageList) DeepCopyInto(out *VirtualImageList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualImage, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMDDataSource. -func (in *VMDDataSource) DeepCopy() *VMDDataSource { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageList. +func (in *VirtualImageList) DeepCopy() *VirtualImageList { if in == nil { return nil } - out := new(VMDDataSource) + out := new(VirtualImageList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualImageList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VMDDownloadSpeed) DeepCopyInto(out *VMDDownloadSpeed) { +func (in *VirtualImageObjectRef) DeepCopyInto(out *VirtualImageObjectRef) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMDDownloadSpeed. -func (in *VMDDownloadSpeed) DeepCopy() *VMDDownloadSpeed { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageObjectRef. +func (in *VirtualImageObjectRef) DeepCopy() *VirtualImageObjectRef { if in == nil { return nil } - out := new(VMDDownloadSpeed) + out := new(VirtualImageObjectRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VMDPersistentVolumeClaim) DeepCopyInto(out *VMDPersistentVolumeClaim) { +func (in *VirtualImagePersistentVolumeClaim) DeepCopyInto(out *VirtualImagePersistentVolumeClaim) { *out = *in - if in.StorageClassName != nil { - in, out := &in.StorageClassName, &out.StorageClassName + if in.StorageClass != nil { + in, out := &in.StorageClass, &out.StorageClass *out = new(string) **out = **in } - if in.Size != nil { - in, out := &in.Size, &out.Size - x := (*in).DeepCopy() - *out = &x - } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMDPersistentVolumeClaim. -func (in *VMDPersistentVolumeClaim) DeepCopy() *VMDPersistentVolumeClaim { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImagePersistentVolumeClaim. +func (in *VirtualImagePersistentVolumeClaim) DeepCopy() *VirtualImagePersistentVolumeClaim { if in == nil { return nil } - out := new(VMDPersistentVolumeClaim) + out := new(VirtualImagePersistentVolumeClaim) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VMIDataSource) DeepCopyInto(out *VMIDataSource) { +func (in *VirtualImageSpec) DeepCopyInto(out *VirtualImageSpec) { *out = *in - if in.HTTP != nil { - in, out := &in.HTTP, &out.HTTP - *out = new(DataSourceHTTP) - (*in).DeepCopyInto(*out) - } - if in.ContainerImage != nil { - in, out := &in.ContainerImage, &out.ContainerImage - *out = new(DataSourceContainerRegistry) - (*in).DeepCopyInto(*out) - } - if in.VirtualMachineImage != nil { - in, out := &in.VirtualMachineImage, &out.VirtualMachineImage - *out = new(DataSourceNamedRef) - **out = **in - } - if in.ClusterVirtualMachineImage != nil { - in, out := &in.ClusterVirtualMachineImage, &out.ClusterVirtualMachineImage - *out = new(DataSourceNamedRef) - **out = **in - } + in.PersistentVolumeClaim.DeepCopyInto(&out.PersistentVolumeClaim) + in.DataSource.DeepCopyInto(&out.DataSource) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMIDataSource. -func (in *VMIDataSource) DeepCopy() *VMIDataSource { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageSpec. +func (in *VirtualImageSpec) DeepCopy() *VirtualImageSpec { if in == nil { return nil } - out := new(VMIDataSource) + out := new(VirtualImageSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VMIPersistentVolumeClaim) DeepCopyInto(out *VMIPersistentVolumeClaim) { +func (in *VirtualImageStatus) DeepCopyInto(out *VirtualImageStatus) { *out = *in - if in.StorageClassName != nil { - in, out := &in.StorageClassName, &out.StorageClassName - *out = new(string) - **out = **in - } + out.ImageStatus = in.ImageStatus return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMIPersistentVolumeClaim. -func (in *VMIPersistentVolumeClaim) DeepCopy() *VMIPersistentVolumeClaim { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualImageStatus. +func (in *VirtualImageStatus) DeepCopy() *VirtualImageStatus { if in == nil { return nil } - out := new(VMIPersistentVolumeClaim) + out := new(VirtualImageStatus) in.DeepCopyInto(out) return out } @@ -890,7 +1005,7 @@ func (in *VirtualMachineBlockDeviceAttachment) DeepCopyInto(out *VirtualMachineB *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + out.Spec = in.Spec out.Status = in.Status return } @@ -949,7 +1064,7 @@ func (in *VirtualMachineBlockDeviceAttachmentList) DeepCopyObject() runtime.Obje // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineBlockDeviceAttachmentSpec) DeepCopyInto(out *VirtualMachineBlockDeviceAttachmentSpec) { *out = *in - in.BlockDevice.DeepCopyInto(&out.BlockDevice) + out.BlockDeviceRef = in.BlockDeviceRef return } @@ -1117,107 +1232,6 @@ func (in *VirtualMachineCPUModelStatusFeatures) DeepCopy() *VirtualMachineCPUMod return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineDisk) DeepCopyInto(out *VirtualMachineDisk) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineDisk. -func (in *VirtualMachineDisk) DeepCopy() *VirtualMachineDisk { - if in == nil { - return nil - } - out := new(VirtualMachineDisk) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *VirtualMachineDisk) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineDiskList) DeepCopyInto(out *VirtualMachineDiskList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]VirtualMachineDisk, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineDiskList. -func (in *VirtualMachineDiskList) DeepCopy() *VirtualMachineDiskList { - if in == nil { - return nil - } - out := new(VirtualMachineDiskList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *VirtualMachineDiskList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineDiskSpec) DeepCopyInto(out *VirtualMachineDiskSpec) { - *out = *in - if in.DataSource != nil { - in, out := &in.DataSource, &out.DataSource - *out = new(VMDDataSource) - (*in).DeepCopyInto(*out) - } - in.PersistentVolumeClaim.DeepCopyInto(&out.PersistentVolumeClaim) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineDiskSpec. -func (in *VirtualMachineDiskSpec) DeepCopy() *VirtualMachineDiskSpec { - if in == nil { - return nil - } - out := new(VirtualMachineDiskSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineDiskStatus) DeepCopyInto(out *VirtualMachineDiskStatus) { - *out = *in - out.DownloadSpeed = in.DownloadSpeed - out.Target = in.Target - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineDiskStatus. -func (in *VirtualMachineDiskStatus) DeepCopy() *VirtualMachineDiskStatus { - if in == nil { - return nil - } - out := new(VirtualMachineDiskStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineIPAddressClaim) DeepCopyInto(out *VirtualMachineIPAddressClaim) { *out = *in @@ -1425,102 +1439,6 @@ func (in *VirtualMachineIPAddressLeaseStatus) DeepCopy() *VirtualMachineIPAddres return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineImage) DeepCopyInto(out *VirtualMachineImage) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineImage. -func (in *VirtualMachineImage) DeepCopy() *VirtualMachineImage { - if in == nil { - return nil - } - out := new(VirtualMachineImage) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *VirtualMachineImage) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineImageList) DeepCopyInto(out *VirtualMachineImageList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]VirtualMachineImage, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineImageList. -func (in *VirtualMachineImageList) DeepCopy() *VirtualMachineImageList { - if in == nil { - return nil - } - out := new(VirtualMachineImageList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *VirtualMachineImageList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineImageSpec) DeepCopyInto(out *VirtualMachineImageSpec) { - *out = *in - in.PersistentVolumeClaim.DeepCopyInto(&out.PersistentVolumeClaim) - in.DataSource.DeepCopyInto(&out.DataSource) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineImageSpec. -func (in *VirtualMachineImageSpec) DeepCopy() *VirtualMachineImageSpec { - if in == nil { - return nil - } - out := new(VirtualMachineImageSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VirtualMachineImageStatus) DeepCopyInto(out *VirtualMachineImageStatus) { - *out = *in - out.ImageStatus = in.ImageStatus - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineImageStatus. -func (in *VirtualMachineImageStatus) DeepCopy() *VirtualMachineImageStatus { - if in == nil { - return nil - } - out := new(VirtualMachineImageStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineList) DeepCopyInto(out *VirtualMachineList) { *out = *in @@ -1688,12 +1606,10 @@ func (in *VirtualMachineSpec) DeepCopyInto(out *VirtualMachineSpec) { } out.CPU = in.CPU out.Memory = in.Memory - if in.BlockDevices != nil { - in, out := &in.BlockDevices, &out.BlockDevices - *out = make([]BlockDeviceSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + if in.BlockDeviceRefs != nil { + in, out := &in.BlockDeviceRefs, &out.BlockDeviceRefs + *out = make([]BlockDeviceSpecRef, len(*in)) + copy(*out, *in) } if in.Provisioning != nil { in, out := &in.Provisioning, &out.Provisioning @@ -1716,12 +1632,10 @@ func (in *VirtualMachineSpec) DeepCopy() *VirtualMachineSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineStatus) DeepCopyInto(out *VirtualMachineStatus) { *out = *in - if in.BlockDevicesAttached != nil { - in, out := &in.BlockDevicesAttached, &out.BlockDevicesAttached - *out = make([]BlockDeviceStatus, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + if in.BlockDeviceRefs != nil { + in, out := &in.BlockDeviceRefs, &out.BlockDeviceRefs + *out = make([]BlockDeviceStatusRef, len(*in)) + copy(*out, *in) } out.GuestOSInfo = in.GuestOSInfo if in.RestartAwaitingChanges != nil { 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 93a35800e..db0e29be5 100644 --- a/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go +++ b/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go @@ -32,27 +32,20 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceAttachmentBlockDevice": schema_virtualization_api_core_v1alpha2_BlockDeviceAttachmentBlockDevice(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceAttachmentVirtualMachineDisk": schema_virtualization_api_core_v1alpha2_BlockDeviceAttachmentVirtualMachineDisk(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceSpec": schema_virtualization_api_core_v1alpha2_BlockDeviceSpec(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceStatus": schema_virtualization_api_core_v1alpha2_BlockDeviceStatus(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceSpecRef": schema_virtualization_api_core_v1alpha2_BlockDeviceSpecRef(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceStatusRef": schema_virtualization_api_core_v1alpha2_BlockDeviceStatusRef(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.CPUSpec": schema_virtualization_api_core_v1alpha2_CPUSpec(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.CVMIDataSource": schema_virtualization_api_core_v1alpha2_CVMIDataSource(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.Checksum": schema_virtualization_api_core_v1alpha2_Checksum(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterImageDeviceSpec": schema_virtualization_api_core_v1alpha2_ClusterImageDeviceSpec(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImage": schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImage(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageList": schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageList(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageSpec": schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageSpec(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageStatus": schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageStatus(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceClusterVirtualMachineImage": schema_virtualization_api_core_v1alpha2_DataSourceClusterVirtualMachineImage(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImage": schema_virtualization_api_core_v1alpha2_ClusterVirtualImage(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.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.DataSourceNameNamespacedRef": schema_virtualization_api_core_v1alpha2_DataSourceNameNamespacedRef(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef": schema_virtualization_api_core_v1alpha2_DataSourceNamedRef(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.DiskDeviceSpec": schema_virtualization_api_core_v1alpha2_DiskDeviceSpec(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.ImageDeviceSpec": schema_virtualization_api_core_v1alpha2_ImageDeviceSpec(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.ImageStatusSize": schema_virtualization_api_core_v1alpha2_ImageStatusSize(ref), @@ -60,12 +53,25 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget": schema_virtualization_api_core_v1alpha2_ImageStatusTarget(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.MemorySpec": schema_virtualization_api_core_v1alpha2_MemorySpec(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.Provisioning": schema_virtualization_api_core_v1alpha2_Provisioning(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.SysprepRef": schema_virtualization_api_core_v1alpha2_SysprepRef(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.UserDataRef": schema_virtualization_api_core_v1alpha2_UserDataRef(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VMAffinity": schema_virtualization_api_core_v1alpha2_VMAffinity(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMDDataSource": schema_virtualization_api_core_v1alpha2_VMDDataSource(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMDDownloadSpeed": schema_virtualization_api_core_v1alpha2_VMDDownloadSpeed(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMDPersistentVolumeClaim": schema_virtualization_api_core_v1alpha2_VMDPersistentVolumeClaim(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMIDataSource": schema_virtualization_api_core_v1alpha2_VMIDataSource(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMIPersistentVolumeClaim": schema_virtualization_api_core_v1alpha2_VMIPersistentVolumeClaim(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.VirtualDiskDataSource": schema_virtualization_api_core_v1alpha2_VirtualDiskDataSource(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskDownloadSpeed": schema_virtualization_api_core_v1alpha2_VirtualDiskDownloadSpeed(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), + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskPersistentVolumeClaim": schema_virtualization_api_core_v1alpha2_VirtualDiskPersistentVolumeClaim(ref), + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskSpec": schema_virtualization_api_core_v1alpha2_VirtualDiskSpec(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.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.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), @@ -79,10 +85,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineCPUModelSpec": schema_virtualization_api_core_v1alpha2_VirtualMachineCPUModelSpec(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineCPUModelStatus": schema_virtualization_api_core_v1alpha2_VirtualMachineCPUModelStatus(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineCPUModelStatusFeatures": schema_virtualization_api_core_v1alpha2_VirtualMachineCPUModelStatusFeatures(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDisk": schema_virtualization_api_core_v1alpha2_VirtualMachineDisk(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskList": schema_virtualization_api_core_v1alpha2_VirtualMachineDiskList(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskSpec": schema_virtualization_api_core_v1alpha2_VirtualMachineDiskSpec(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskStatus": schema_virtualization_api_core_v1alpha2_VirtualMachineDiskStatus(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineIPAddressClaim": schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaim(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineIPAddressClaimList": schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaimList(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineIPAddressClaimSpec": schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaimSpec(ref), @@ -92,10 +94,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineIPAddressLeaseList": schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressLeaseList(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineIPAddressLeaseSpec": schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressLeaseSpec(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineIPAddressLeaseStatus": schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressLeaseStatus(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImage": schema_virtualization_api_core_v1alpha2_VirtualMachineImage(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageList": schema_virtualization_api_core_v1alpha2_VirtualMachineImageList(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageSpec": schema_virtualization_api_core_v1alpha2_VirtualMachineImageSpec(ref), - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageStatus": schema_virtualization_api_core_v1alpha2_VirtualMachineImageStatus(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineList": schema_virtualization_api_core_v1alpha2_VirtualMachineList(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineOperation": schema_virtualization_api_core_v1alpha2_VirtualMachineOperation(ref), "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineOperationList": schema_virtualization_api_core_v1alpha2_VirtualMachineOperationList(ref), @@ -628,39 +626,19 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA } } -func schema_virtualization_api_core_v1alpha2_BlockDeviceAttachmentBlockDevice(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_BlockDeviceSpecRef(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "type": { + "kind": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, Format: "", }, }, - "virtualMachineDisk": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceAttachmentVirtualMachineDisk"), - }, - }, - }, - Required: []string{"type", "virtualMachineDisk"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceAttachmentVirtualMachineDisk"}, - } -} - -func schema_virtualization_api_core_v1alpha2_BlockDeviceAttachmentVirtualMachineDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ Default: "", @@ -669,77 +647,32 @@ func schema_virtualization_api_core_v1alpha2_BlockDeviceAttachmentVirtualMachine }, }, }, - Required: []string{"name"}, + Required: []string{"kind", "name"}, }, }, } } -func schema_virtualization_api_core_v1alpha2_BlockDeviceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_BlockDeviceStatusRef(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "type": { + "kind": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, Format: "", }, }, - "virtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageDeviceSpec"), - }, - }, - "clusterVirtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterImageDeviceSpec"), - }, - }, - "virtualMachineDisk": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DiskDeviceSpec"), - }, - }, - }, - Required: []string{"type"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterImageDeviceSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.DiskDeviceSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageDeviceSpec"}, - } -} - -func schema_virtualization_api_core_v1alpha2_BlockDeviceStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "type": { + "name": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, Format: "", }, }, - "virtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageDeviceSpec"), - }, - }, - "clusterVirtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterImageDeviceSpec"), - }, - }, - "virtualMachineDisk": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DiskDeviceSpec"), - }, - }, "hotpluggable": { SchemaProps: spec.SchemaProps{ Default: false, @@ -762,11 +695,9 @@ func schema_virtualization_api_core_v1alpha2_BlockDeviceStatus(ref common.Refere }, }, }, - Required: []string{"type", "virtualMachineImage", "clusterVirtualMachineImage", "virtualMachineDisk", "hotpluggable", "target", "size"}, + Required: []string{"kind", "name", "hotpluggable", "target", "size"}, }, }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterImageDeviceSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.DiskDeviceSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageDeviceSpec"}, } } @@ -776,7 +707,7 @@ func schema_virtualization_api_core_v1alpha2_CPUSpec(ref common.ReferenceCallbac SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "modelName": { + "virtualMachineCPUModel": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -798,49 +729,9 @@ func schema_virtualization_api_core_v1alpha2_CPUSpec(ref common.ReferenceCallbac }, }, }, - Required: []string{"modelName", "cores", "coreFraction"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_CVMIDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "type": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "http": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP"), - }, - }, - "containerImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), - }, - }, - "virtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNameNamespacedRef"), - }, - }, - "clusterVirtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef"), - }, - }, - }, + Required: []string{"virtualMachineCPUModel", "cores", "coreFraction"}, }, }, - 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.DataSourceNameNamespacedRef", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef"}, } } @@ -868,31 +759,11 @@ func schema_virtualization_api_core_v1alpha2_Checksum(ref common.ReferenceCallba } } -func schema_virtualization_api_core_v1alpha2_ClusterImageDeviceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"name"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImage(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImage(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ClusterVirtualMachineImage is a cluster wide available image for virtual machines.", + Description: "ClusterVirtualImage is a cluster wide available image for virtual machines.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -918,13 +789,13 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImage(ref comm "spec": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageSpec"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageSpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageStatus"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageStatus"), }, }, }, @@ -932,15 +803,50 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImage(ref comm }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "http": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP"), + }, + }, + "containerImage": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), + }, + }, + "objectRef": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageObjectRef"), + }, + }, + }, + }, + }, + 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"}, } } -func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ClusterVirtualMachineImageList provides the needed parameters to do request a list of ClusterVirtualMachineImages from the system.", + Description: "ClusterVirtualImageList provides the needed parameters to do request a list of ClusterVirtualImages from the system.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -971,7 +877,7 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageList(ref Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImage"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImage"), }, }, }, @@ -982,11 +888,41 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageList(ref }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualMachineImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageObjectRef(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, } } -func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -995,7 +931,7 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageSpec(ref "dataSource": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.CVMIDataSource"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageDataSource"), }, }, }, @@ -1003,11 +939,11 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageSpec(ref }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.CVMIDataSource"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.ClusterVirtualImageDataSource"}, } } -func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ClusterVirtualImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1040,7 +976,7 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageStatus(re }, "capacity": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -1100,26 +1036,6 @@ func schema_virtualization_api_core_v1alpha2_ClusterVirtualMachineImageStatus(re } } -func schema_virtualization_api_core_v1alpha2_DataSourceClusterVirtualMachineImage(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"name"}, - }, - }, - } -} - func schema_virtualization_api_core_v1alpha2_DataSourceContainerRegistry(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1187,20 +1103,13 @@ func schema_virtualization_api_core_v1alpha2_DataSourceHTTP(ref common.Reference } } -func schema_virtualization_api_core_v1alpha2_DataSourceNameNamespacedRef(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_DiskTarget(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "namespace": { + "persistentVolumeClaim": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -1208,33 +1117,34 @@ func schema_virtualization_api_core_v1alpha2_DataSourceNameNamespacedRef(ref com }, }, }, - Required: []string{"name", "namespace"}, + Required: []string{"persistentVolumeClaim"}, }, }, } } -func schema_virtualization_api_core_v1alpha2_DataSourceNamedRef(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_Disruptions(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "name": { + "restartApprovalMode": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "RestartApprovalMode defines a restart approving mode: Manual or Automatic.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, }, - Required: []string{"name"}, + Required: []string{"restartApprovalMode"}, }, }, } } -func schema_virtualization_api_core_v1alpha2_DiskDeviceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ImagePullSecret(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1247,20 +1157,7 @@ func schema_virtualization_api_core_v1alpha2_DiskDeviceSpec(ref common.Reference Format: "", }, }, - }, - Required: []string{"name"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_DiskTarget(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "persistentVolumeClaimName": { + "namespace": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -1268,93 +1165,25 @@ func schema_virtualization_api_core_v1alpha2_DiskTarget(ref common.ReferenceCall }, }, }, - Required: []string{"persistentVolumeClaimName"}, + Required: []string{"name", "namespace"}, }, }, } } -func schema_virtualization_api_core_v1alpha2_Disruptions(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_ImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "restartApprovalMode": { + "importDuration": { SchemaProps: spec.SchemaProps{ - Description: "RestartApprovalMode defines a restart approving mode: Manual or Automatic.", - Default: "", - Type: []string{"string"}, - Format: "", + Type: []string{"string"}, + Format: "", }, }, - }, - Required: []string{"restartApprovalMode"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_ImageDeviceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"name"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_ImagePullSecret(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "namespace": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"name", "namespace"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_ImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "importDuration": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "downloadSpeed": { + "downloadSpeed": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSpeed"), @@ -1375,7 +1204,7 @@ func schema_virtualization_api_core_v1alpha2_ImageStatus(ref common.ReferenceCal }, "capacity": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -1527,7 +1356,7 @@ func schema_virtualization_api_core_v1alpha2_ImageStatusTarget(ref common.Refere }, "persistentVolumeClaimName": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -1572,20 +1401,20 @@ func schema_virtualization_api_core_v1alpha2_Provisioning(ref common.ReferenceCa Format: "", }, }, - "sysprepSecretRef": { - SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), - }, - }, "userData": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, Format: "", }, }, - "userDataSecretRef": { + "userDataRef": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.UserDataRef"), + }, + }, + "sysprepRef": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.SysprepRef"), }, }, }, @@ -1593,7 +1422,61 @@ func schema_virtualization_api_core_v1alpha2_Provisioning(ref common.ReferenceCa }, }, Dependencies: []string{ - "k8s.io/api/core/v1.LocalObjectReference"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.SysprepRef", "github.com/deckhouse/virtualization/api/core/v1alpha2.UserDataRef"}, + } +} + +func schema_virtualization_api_core_v1alpha2_SysprepRef(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"kind", "name"}, + }, + }, + } +} + +func schema_virtualization_api_core_v1alpha2_UserDataRef(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"kind", "name"}, + }, + }, } } @@ -1626,7 +1509,79 @@ func schema_virtualization_api_core_v1alpha2_VMAffinity(ref common.ReferenceCall } } -func schema_virtualization_api_core_v1alpha2_VMDDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_VMBDAObjectRef(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VirtualDisk is a disk ready to be bound by a VM", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualDiskDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1648,25 +1603,20 @@ func schema_virtualization_api_core_v1alpha2_VMDDataSource(ref common.ReferenceC Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), }, }, - "virtualMachineImage": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef"), - }, - }, - "clusterVirtualMachineImage": { + "objectRef": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskObjectRef"), }, }, }, }, }, 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.DataSourceNamedRef"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry", "github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskObjectRef"}, } } -func schema_virtualization_api_core_v1alpha2_VMDDownloadSpeed(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_VirtualDiskDownloadSpeed(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1702,13 +1652,86 @@ func schema_virtualization_api_core_v1alpha2_VMDDownloadSpeed(ref common.Referen } } -func schema_virtualization_api_core_v1alpha2_VMDPersistentVolumeClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_VirtualDiskList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VirtualDiskList contains a list of VirtualDisk", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDisk"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDisk", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualDiskObjectRef(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualDiskPersistentVolumeClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "storageClassName": { + "storageClass": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, Format: "", @@ -1727,61 +1750,403 @@ func schema_virtualization_api_core_v1alpha2_VMDPersistentVolumeClaim(ref common } } -func schema_virtualization_api_core_v1alpha2_VMIDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_api_core_v1alpha2_VirtualDiskSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "type": { + "dataSource": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskDataSource"), }, }, - "http": { + "persistentVolumeClaim": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP"), + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskPersistentVolumeClaim"), + }, + }, + }, + Required: []string{"persistentVolumeClaim"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskDataSource", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskPersistentVolumeClaim"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "importDuration": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "downloadSpeed": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskDownloadSpeed"), + }, + }, + "capacity": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "target": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DiskTarget"), + }, + }, + "progress": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "uploadCommand": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "phase": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "failureReason": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "failureMessage": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"downloadSpeed", "target", "phase", "failureReason", "failureMessage"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.DiskTarget", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskDownloadSpeed"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImage(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VirtualImage is an image for virtual machines available in the particular namespace.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImageDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "http": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceHTTP"), + }, + }, + "containerImage": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), + }, + }, + "objectRef": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageObjectRef"), + }, + }, + }, + }, + }, + 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"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VirtualImageList provides the needed parameters to do request a list of VirtualImages from the system.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "Items provides a list of CDIs", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImage"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImageObjectRef(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImagePersistentVolumeClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "storageClass": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "storage": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "persistentVolumeClaim": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImagePersistentVolumeClaim"), + }, + }, + "dataSource": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageDataSource"), + }, + }, + }, + Required: []string{"storage", "persistentVolumeClaim", "dataSource"}, + }, + }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImageDataSource", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualImagePersistentVolumeClaim"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "importDuration": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "downloadSpeed": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSpeed"), + }, + }, + "size": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), + }, + }, + "format": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "capacity": { + SchemaProps: spec.SchemaProps{ + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", + 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{ + Default: "", + Type: []string{"string"}, + Format: "", }, }, - "containerImage": { + "progress": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceContainerRegistry"), + Type: []string{"string"}, + Format: "", }, }, - "virtualMachineImage": { + "uploadCommand": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef"), + Type: []string{"string"}, + Format: "", }, }, - "clusterVirtualMachineImage": { + "failureReason": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DataSourceNamedRef"), + Default: "", + Type: []string{"string"}, + Format: "", }, }, - }, - }, - }, - 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.DataSourceNamedRef"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VMIPersistentVolumeClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "storageClassName": { + "failureMessage": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Default: "", + Type: []string{"string"}, + Format: "", }, }, }, + Required: []string{"downloadSpeed", "size", "format", "cdrom", "target", "phase", "failureReason", "failureMessage"}, }, }, + Dependencies: []string{ + "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSpeed", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget"}, } } @@ -2091,25 +2456,25 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineBlockDeviceAttachment SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, Format: "", }, }, - "blockDevice": { + "blockDeviceRef": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceAttachmentBlockDevice"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VMBDAObjectRef"), }, }, }, - Required: []string{"virtualMachineName", "blockDevice"}, + Required: []string{"virtualMachine", "blockDeviceRef"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceAttachmentBlockDevice"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.VMBDAObjectRef"}, } } @@ -2119,7 +2484,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineBlockDeviceAttachment SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, Format: "", @@ -2313,243 +2678,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineCPUModelStatus(ref co }, }, }, - "phase": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"phase"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineCPUModelStatusFeatures"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineCPUModelStatusFeatures(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "enabled": { - SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - "notEnabledCommon": { - SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - }, - Required: []string{"enabled", "notEnabledCommon"}, - }, - }, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineDisk is a disk ready to be bound by a VM", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "kind": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "apiVersion": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "metadata": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), - }, - }, - "spec": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskSpec"), - }, - }, - "status": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskStatus"), - }, - }, - }, - Required: []string{"spec"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDiskStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineDiskList(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineDiskList contains a list of VirtualMachineDisk", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "kind": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "apiVersion": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "metadata": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), - }, - }, - "items": { - SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDisk"), - }, - }, - }, - }, - }, - }, - Required: []string{"metadata", "items"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineDisk", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineDiskSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "dataSource": { - SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VMDDataSource"), - }, - }, - "persistentVolumeClaim": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VMDPersistentVolumeClaim"), - }, - }, - }, - Required: []string{"persistentVolumeClaim"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMDDataSource", "github.com/deckhouse/virtualization/api/core/v1alpha2.VMDPersistentVolumeClaim"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineDiskStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "importDuration": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "downloadSpeed": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VMDDownloadSpeed"), - }, - }, - "capacity": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "target": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.DiskTarget"), - }, - }, - "progress": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "uploadCommand": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "phase": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "failureReason": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "failureMessage": { + "phase": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -2557,11 +2686,52 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineDiskStatus(ref common }, }, }, - Required: []string{"downloadSpeed", "target", "phase", "failureReason", "failureMessage"}, + Required: []string{"phase"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.DiskTarget", "github.com/deckhouse/virtualization/api/core/v1alpha2.VMDDownloadSpeed"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineCPUModelStatusFeatures"}, + } +} + +func schema_virtualization_api_core_v1alpha2_VirtualMachineCPUModelStatusFeatures(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "enabled": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "notEnabledCommon": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"enabled", "notEnabledCommon"}, + }, + }, } } @@ -2668,7 +2838,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaimSpec(re Description: "VirtualMachineIPAddressClaimSpec is the desired state of `VirtualMachineIPAddressClaim`.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "leaseName": { + "virtualMachineIPAddressLease": { SchemaProps: spec.SchemaProps{ Description: "The issued `VirtualMachineIPAddressLease`, managed automatically.", Default: "", @@ -2692,7 +2862,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaimSpec(re }, }, }, - Required: []string{"leaseName", "address"}, + Required: []string{"virtualMachineIPAddressLease", "address"}, }, }, } @@ -2705,7 +2875,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaimStatus( Description: "VirtualMachineIPAddressClaimStatus is the observed state of `VirtualMachineIPAddressClaim`.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Description: "Represents the virtual machine that currently uses this IP address.", Type: []string{"string"}, @@ -2719,7 +2889,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressClaimStatus( Format: "", }, }, - "leaseName": { + "virtualMachineIPAddressLease": { SchemaProps: spec.SchemaProps{ Description: "The issued `VirtualMachineIPAddressLease`, managed automatically.", Type: []string{"string"}, @@ -2919,231 +3089,6 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineIPAddressLeaseStatus( } } -func schema_virtualization_api_core_v1alpha2_VirtualMachineImage(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineImage is an image for virtual machines available in the particular namespace.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "kind": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "apiVersion": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "metadata": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), - }, - }, - "spec": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageSpec"), - }, - }, - "status": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageStatus"), - }, - }, - }, - Required: []string{"spec"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineImageList provides the needed parameters to do request a list of ClusterVirtualMachineImages from the system.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "kind": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "apiVersion": { - SchemaProps: spec.SchemaProps{ - 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{"string"}, - Format: "", - }, - }, - "metadata": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), - }, - }, - "items": { - SchemaProps: spec.SchemaProps{ - Description: "Items provides a list of CDIs", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImage"), - }, - }, - }, - }, - }, - }, - Required: []string{"metadata", "items"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualMachineImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "storage": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "persistentVolumeClaim": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VMIPersistentVolumeClaim"), - }, - }, - "dataSource": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VMIDataSource"), - }, - }, - }, - Required: []string{"storage", "persistentVolumeClaim", "dataSource"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.VMIDataSource", "github.com/deckhouse/virtualization/api/core/v1alpha2.VMIPersistentVolumeClaim"}, - } -} - -func schema_virtualization_api_core_v1alpha2_VirtualMachineImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "importDuration": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "downloadSpeed": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSpeed"), - }, - }, - "size": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize"), - }, - }, - "format": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "capacity": { - SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", - 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{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "progress": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "uploadCommand": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "failureReason": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "failureMessage": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"downloadSpeed", "size", "format", "cdrom", "target", "phase", "failureReason", "failureMessage"}, - }, - }, - Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSize", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusSpeed", "github.com/deckhouse/virtualization/api/core/v1alpha2.ImageStatusTarget"}, - } -} - func schema_virtualization_api_core_v1alpha2_VirtualMachineList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3303,7 +3248,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineOperationSpec(ref com Format: "", }, }, - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -3317,7 +3262,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineOperationSpec(ref com }, }, }, - Required: []string{"type", "virtualMachineName"}, + Required: []string{"type", "virtualMachine"}, }, }, } @@ -3369,9 +3314,9 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineSpec(ref common.Refer Format: "", }, }, - "virtualMachineIPAddressClaimName": { + "virtualMachineIPAddressClaim": { SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineIPAddressClaimName specifies a name for the associated `VirtualMahcineIPAddressClaim` resource. Defaults to `{vm name}`.", + Description: "VirtualMachineIPAddressClaim specifies a name for the associated `VirtualMachineIPAddressClaim` resource. Defaults to `{vm name}`.", Type: []string{"string"}, Format: "", }, @@ -3479,14 +3424,14 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineSpec(ref common.Refer Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.MemorySpec"), }, }, - "blockDevices": { + "blockDeviceRefs": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceSpec"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceSpecRef"), }, }, }, @@ -3498,11 +3443,11 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineSpec(ref common.Refer }, }, }, - Required: []string{"runPolicy", "priorityClassName", "disruptions", "enableParavirtualization", "cpu", "memory", "blockDevices", "provisioning"}, + Required: []string{"runPolicy", "priorityClassName", "disruptions", "enableParavirtualization", "cpu", "memory", "blockDeviceRefs", "provisioning"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.CPUSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.Disruptions", "github.com/deckhouse/virtualization/api/core/v1alpha2.MemorySpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.Provisioning", "github.com/deckhouse/virtualization/api/core/v1alpha2.VMAffinity", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceSpecRef", "github.com/deckhouse/virtualization/api/core/v1alpha2.CPUSpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.Disruptions", "github.com/deckhouse/virtualization/api/core/v1alpha2.MemorySpec", "github.com/deckhouse/virtualization/api/core/v1alpha2.Provisioning", "github.com/deckhouse/virtualization/api/core/v1alpha2.VMAffinity", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint"}, } } @@ -3519,14 +3464,14 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineStatus(ref common.Ref Format: "", }, }, - "nodeName": { + "node": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, Format: "", }, }, - "ipAddressClaim": { + "virtualMachineIPAddressClaim": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -3540,14 +3485,14 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineStatus(ref common.Ref Format: "", }, }, - "blockDevicesAttached": { + "blockDeviceRefs": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceStatus"), + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceStatusRef"), }, }, }, @@ -3580,11 +3525,11 @@ func schema_virtualization_api_core_v1alpha2_VirtualMachineStatus(ref common.Ref }, }, }, - Required: []string{"phase", "nodeName", "ipAddressClaim", "ipAddress", "blockDevicesAttached", "guestOSInfo", "message"}, + Required: []string{"phase", "node", "virtualMachineIPAddressClaim", "ipAddress", "blockDeviceRefs", "guestOSInfo", "message"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceStatus", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.JSON", "kubevirt.io/api/core/v1.VirtualMachineInstanceGuestOSInfo"}, + "github.com/deckhouse/virtualization/api/core/v1alpha2.BlockDeviceStatusRef", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.JSON", "kubevirt.io/api/core/v1.VirtualMachineInstanceGuestOSInfo"}, } } diff --git a/crds/clustervirtualmachineimage.yaml b/crds/clustervirtualimage.yaml similarity index 85% rename from crds/clustervirtualmachineimage.yaml rename to crds/clustervirtualimage.yaml index dff55ced3..bbc3d0bca 100644 --- a/crds/clustervirtualmachineimage.yaml +++ b/crds/clustervirtualimage.yaml @@ -1,7 +1,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: clustervirtualmachineimages.virtualization.deckhouse.io + name: clustervirtualimages.virtualization.deckhouse.io labels: heritage: deckhouse module: virtualization @@ -11,12 +11,12 @@ spec: names: categories: - virtualization - plural: clustervirtualmachineimages - singular: clustervirtualmachineimage - kind: ClusterVirtualMachineImage + plural: clustervirtualimages + singular: clustervirtualimage + kind: ClusterVirtualImage shortNames: - - cvmi - - cvmis + - cvi + - cvis preserveUnknownFields: false versions: - name: v1alpha2 @@ -26,7 +26,7 @@ spec: openAPIV3Schema: type: object description: | - Describes a virtual machine disk image that can be used as a data source for new `VirtualMachineDisks` or an installation image (iso) to be mounted in `VirtualMachines` directly. This resource type is available for all namespaces in the cluster. + 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. @@ -49,16 +49,14 @@ spec: enum: - "HTTP" - "ContainerImage" - - "VirtualMachineImage" - - "ClusterVirtualMachineImage" + - "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. - * `VirtualMachineImage` — create an image from another existing `VirtualMachineImage`. - * `ClusterVirtualMachineImage` — create an image from another existing `ClusterVirtualMachineImage`. + * `ObjectRef` — fill the cluster image from another existing `VirtualImage` or `ClusterVirtualImage`. * `Upload` — fill the image with data, uploaded by user via the special interface. http: type: object @@ -151,33 +149,25 @@ spec: The CA chain in base64 format to verify the container registry. example: | YWFhCg== - virtualMachineImage: + objectRef: type: object - description: | - Use another existing `VirtualMachineImage`. - required: - - name - - namespace + description: Reference to existing `VirtualImage` or `ClusterVirtualImage`. + required: ["kind", "name"] properties: + kind: + type: string + description: A kind of existing `VirtualImage` or `ClusterVirtualImage`. + enum: + - "ClusterVirtualImage" + - "VirtualImage" name: type: string description: | - A name of existing `VirtualMachineImage`. + A name of existing `VirtualImage` or `ClusterVirtualImage`. namespace: type: string description: | - A namespace where `VirtualMachineImage` is located. - clusterVirtualMachineImage: - type: object - description: | - Use another existing `ClusterVirtualMachineImage`. - required: - - name - properties: - name: - type: string - description: | - A name of existing `ClusterVirtualMachineImage`. + A namespace where `VirtualImage` is located. oneOf: - properties: type: @@ -191,14 +181,9 @@ spec: required: ["containerImage"] - properties: type: - enum: ["VirtualMachineImage"] - virtualMachineImage: {} - required: ["virtualMachineImage"] - - properties: - type: - enum: ["ClusterVirtualMachineImage"] - clusterVirtualMachineImage: {} - required: ["clusterVirtualMachineImage"] + enum: ["ObjectRef"] + objectRef: {} + required: ["objectRef"] - properties: type: enum: ["Upload"] @@ -273,13 +258,13 @@ spec: properties: registryURL: type: string - example: dvcr.svc./cvmi/:latest + example: dvcr..svc/cvi/:latest description: | Created image in DVCR. phase: type: string description: | - Current status of `ClusterVirtualMachineImage` resource: + 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`. @@ -316,7 +301,7 @@ spec: usedInVMs: type: array description: | - A list of virtual machines and namespaces that use the image + A list of virtual s and namespaces that use the image example: [ { name: "VM100", namespace: "customer1" }, diff --git a/crds/doc-ru-clustervirtualmachineimage.yaml b/crds/doc-ru-clustervirtualimage.yaml similarity index 92% rename from crds/doc-ru-clustervirtualmachineimage.yaml rename to crds/doc-ru-clustervirtualimage.yaml index 4b5066fc9..12cc8511b 100644 --- a/crds/doc-ru-clustervirtualmachineimage.yaml +++ b/crds/doc-ru-clustervirtualimage.yaml @@ -4,7 +4,7 @@ spec: schema: openAPIV3Schema: description: | - Описывает образ диска виртуальной машины, который может использоваться в качестве источника данных для новых `VirtualMachineDisks` или установочный образ (iso), который быть смонтирован в `VirtualMachines` напрямую. Этот тип ресурса доступен для всех пространств имен в кластере. + Описывает образ диска виртуальной машины, который может использоваться в качестве источника данных для новых `VirtualDisks` или установочный образ (iso), который быть смонтирован в `VirtualMachines` напрямую. Этот тип ресурса доступен для всех пространств имен в кластере. > Этот ресурс не может быть изменен после его создания. @@ -22,8 +22,8 @@ spec: * `HTTP` — создать образ из файла, опубликованного на HTTP/HTTPS-сервере. * `ContainerImage` — создать образ из образа в container registry. - * `VirtualMachineImage` — создать новый образ из существующего `VirtualMachineImage`. - * `ClusterVirtualMachineImage` — создать новый образ из существующего `ClusterVirtualMachineImage`. + * `VirtualImage` — создать новый образ из существующего `VirtualImage`. + * `ClusterVirtualImage` — создать новый образ из существующего `ClusterVirtualImage`. * `Upload` — загрузить образ вручную, через веб-интерфейс. http: description: | @@ -82,23 +82,23 @@ spec: caBundle: description: | Цепочка сертификатов в формате Base64 для проверки подключения к container registry. - virtualMachineImage: + virtualImage: description: | - Использование существующего `VirtualMachineImage`. + Использование существующего `VirtualImage`. properties: name: description: | - Имя существующего `VirtualMachineImage`. + Имя существующего `VirtualImage`. namespace: description: | - Пространство имен, где `VirtualMachineImage` расположен. - clusterVirtualMachineImage: + Пространство имен, где `VirtualImage` расположен. + clusterVirtualImage: description: | - Использовать существующий `ClusterVirtualMachineImage`. + Использовать существующий `ClusterVirtualImage`. properties: name: description: | - Имя существующего `ClusterVirtualMachineImage`. + Имя существующего `ClusterVirtualImage`. status: properties: importDuration: @@ -148,7 +148,7 @@ spec: Образ, созданный в DVCR. phase: description: | - Текущее состояние ресурса `ClusterVirtualMachineImage`: + Текущее состояние ресурса `ClusterVirtualImage`: * Pending - Ресурс был создан и находится в очереди ожидания. * Provisioning - Идет процесс создания ресурса (копирование/загрузка/создание образа). diff --git a/crds/doc-ru-virtualmachinedisk.yaml b/crds/doc-ru-virtualdisk.yaml similarity index 94% rename from crds/doc-ru-virtualmachinedisk.yaml rename to crds/doc-ru-virtualdisk.yaml index 8ed05c94a..52e6ca84f 100644 --- a/crds/doc-ru-virtualmachinedisk.yaml +++ b/crds/doc-ru-virtualdisk.yaml @@ -17,7 +17,7 @@ spec: size: description: | Желаемый размер PVC для хранения диска. Если диск создается из образа, то размер должен быть не меньше, чем исходный образ в распакованном состоянии. - storageClassName: + storageClass: description: | Имя класса StorageClass, требуемого для PersistentVolumeClaim. Дополнительная информация — https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. dataSource: @@ -30,8 +30,8 @@ spec: * `HTTP` — создать диск из файла, опубликованного на HTTP/HTTPS-сервере. * `ContainerImage` — создать диск из образа в container registry. - * `VirtualMachineImage` — создать диск из существующего `VirtualMachineImage`. - * `ClusterVirtualMachineImage` — создать диск из существующего `ClusterVirtualMachineImage`. + * `VirtualImage` — создать диск из существующего `VirtualImage`. + * `ClusterVirtualImage` — создать диск из существующего `ClusterVirtualImage`. * `Upload` — загрузить образ диска вручную, через веб-интерфейс. http: description: | @@ -84,20 +84,20 @@ spec: caBundle: description: | Цепочка сертификатов в формате Base64 для проверки подключения к container registry. - virtualMachineImage: + virtualImage: description: | - Используйте существующий `VirtualMachineImage`. + Используйте существующий `VirtualImage`. properties: name: description: | - Имя существующего `VirtualMachineImage`. - clusterVirtualMachineImage: + Имя существующего `VirtualImage`. + clusterVirtualImage: description: | - Использовать существующий `ClusterVirtualMachineImage`. + Использовать существующий `ClusterVirtualImage`. properties: name: description: | - Имя существующего `ClusterVirtualMachineImage`. + Имя существующего `ClusterVirtualImage`. status: properties: importDuration: @@ -124,13 +124,13 @@ spec: Емкость PVC в человекочитаемом формате. target: properties: - persistentVolumeClaimName: + persistentVolumeClaim: description: | Имя созданного PersistentVolumeClaim для хранилища Kubernetes. phase: type: string description: | - Текущее состояние ресурса `VirtualMachineDisk`: + Текущее состояние ресурса `VirtualDisk`: * Pending — ресурс был создан и находится в очереди ожидания. * Provisioning — идет процесс создания ресурса (копирование/загрузка/создание образа). diff --git a/crds/doc-ru-virtualmachineimage.yaml b/crds/doc-ru-virtualimage.yaml similarity index 93% rename from crds/doc-ru-virtualmachineimage.yaml rename to crds/doc-ru-virtualimage.yaml index 2e22009ec..5859f852a 100644 --- a/crds/doc-ru-virtualmachineimage.yaml +++ b/crds/doc-ru-virtualimage.yaml @@ -5,7 +5,7 @@ spec: openAPIV3Schema: type: object description: | - Описывает образ диска виртуальной машины, который может использоваться в качестве источника данных для новых `VirtualMachineDisks` или установочный образ (iso), который быть смонтирован в `VirtualMachines` напрямую. + Описывает образ диска виртуальной машины, который может использоваться в качестве источника данных для новых `VirtualDisks` или установочный образ (iso), который быть смонтирован в `VirtualMachines` напрямую. > Этот ресурс не может быть изменен после его создания. @@ -28,8 +28,8 @@ spec: * `HTTP` — создать образ из файла, опубликованного на HTTP/HTTPS-сервере. * `ContainerImage` — создать образ из образа в container registry. - * `VirtualMachineImage` — создать образ из другого существующего `VirtualMachineImage`. - * `ClusterVirtualMachineImage` — создать образ из другого существующего `ClusterVirtualMachineImage`. + * `VirtualImage` — создать образ из другого существующего `VirtualImage`. + * `ClusterVirtualImage` — создать образ из другого существующего `ClusterVirtualImage`. * `Upload` — загрузить образ вручную, через веб-интерфейс. http: description: | @@ -85,23 +85,23 @@ spec: caBundle: description: | Цепочка сертификатов в формате Base64 для проверки подключения к container registry. - virtualMachineImage: + virtualImage: description: | - Используйте существующий `VirtualMachineImage`. + Используйте существующий `VirtualImage`. properties: name: description: | - Имя существующего `VirtualMachineImage`. + Имя существующего `VirtualImage`. namespace: description: | - Пространство имен, где `VirtualMachineImage` расположен. - clusterVirtualMachineImage: + Пространство имен, где `VirtualImage` расположен. + clusterVirtualImage: description: | - Использовать существующий `ClusterVirtualMachineImage`. + Использовать существующий `ClusterVirtualImage`. properties: name: description: | - Имя существующего `ClusterVirtualMachineImage`. + Имя существующего `ClusterVirtualImage`. status: type: object properties: @@ -150,12 +150,12 @@ spec: registryURL: description: | Образ, созданный в DVCR. - persistentVolumeClaimName: + persistentVolumeClaim: description: | Имя созданного PersistentVolumeClaim для хранилища Kubernetes. phase: description: | - Текущее состояние ресурса `VirtualMachineImage`: + Текущее состояние ресурса `VirtualImage`: * Pending — ресурс был создан и находится в очереди ожидания. * Provisioning — идет процесс создания ресурса (копирование/загрузка/создание образа). diff --git a/crds/doc-ru-virtualmachine.yaml b/crds/doc-ru-virtualmachine.yaml index f878cf028..6d10bc0b7 100644 --- a/crds/doc-ru-virtualmachine.yaml +++ b/crds/doc-ru-virtualmachine.yaml @@ -17,19 +17,33 @@ spec: Поддерживаемые параметры для использования сценария инициализации: * UserData — позволяет указать сценарий cloud-init в секции .spec.provisioning.UserData. - * UserDataSecret — позволяет использовать существующий Secret со сценарием cloud-init. + * UserDataRef — позволяет использовать существующий Secret со сценарием cloud-init. + * SysprepRef — позволяет автоматизировать установку Windows. Дополнительная информация: https://cloudinit.readthedocs.io/en/latest/reference/examples.html userData: description: | Сценарий cloud-init. - userDataSecretRef: + userDataRef: description: | - Ссылка на существующий Secret со сценарием cloud-init. + Ссылка на существующий ресурс со сценарием cloud-init. properties: + kind: + description: | + Тип ресурса. name: description: | - Имя Secret со сценарием cloud-init. + Имя ресурса со сценарием cloud-init. + sysprepRef: + description: | + Ссылка на существующий ресурс со сценарием автоматизации Windows. + properties: + kind: + description: | + Тип ресурса. + name: + description: | + Имя ресурса со сценарием автоматизации. runPolicy: description: | Этот параметр определяет политику запуска ВМ: @@ -39,7 +53,7 @@ spec: * `Manual` — после создания ВМ выключается, состояние ВМ (включение/выключение) контролируется через API-сервисы или средствами ОС. * `AlwaysOnUnlessStoppedManually` — после создания ВМ всегда находится в работающем состоянии, даже в случае ее выключения средствами ОС, ВМ может быть выключена с помощью соответствующего API-сервиса. - virtualMachineIPAddressClaimName: + virtualMachineIPAddressClaim: description: | Имя для связанного ресурса `VirtualMahcineIPAddressClaim`. @@ -450,42 +464,23 @@ spec: description: | Объем оперативной памяти. - blockDevices: + blockDeviceRefs: description: | Список блочных устройств, которые могут быть смонтированы в ВМ. Порядок загрузки определяется порядком в списке. items: properties: - type: + kind: description: | Поддерживаемые типы: - * `ClusterVirtualMachineImage` — использовать `ClusterVirtualMachineImage` в качестве диска. Этот тип всегда монтируется в режиме для чтения (ReadOnly). Если образ является ISO-образом, он будет смонтирован как устройство CDROM. - * `VirtualMachineImage` — использовать `VirtualMachineImage` в качестве диска. Этот тип всегда монтируется в режиме для чтения (ReadOnly). Если образ является ISO-образом, он будет смонтирован как устройство CDROM. - * `VirtualMachineDisk` — используйте `VirtualMachineDisk` в качестве диска. Этот тип всегда монтируется в режиме для чтения и записи (ReadWrite). - clusterVirtualMachineImage: - description: | - Использовать `ClusterVirtualMachineImage` в качестве диска. - Этот тип всегда монтируется в режиме для чтения (ReadOnly). Если образ является ISO-образом, он будет смонтирован как устройство CDROM. - properties: - name: - description: | - Имя ресурса `ClusterVirtualMachineImage`. - virtualMachineImage: + * `ClusterVirtualImage` — использовать `ClusterVirtualImage` в качестве диска. Этот тип всегда монтируется в режиме для чтения (ReadOnly). Если образ является ISO-образом, он будет смонтирован как устройство CDROM. + * `VirtualImage` — использовать `VirtualImage` в качестве диска. Этот тип всегда монтируется в режиме для чтения (ReadOnly). Если образ является ISO-образом, он будет смонтирован как устройство CDROM. + * `VirtualDisk` — используйте `VirtualDisk` в качестве диска. Этот тип всегда монтируется в режиме для чтения и записи (ReadWrite). + name: description: | - Использовать `VirtualMachineImage` в качестве диска. Образ с хранилищем ContainerRegistry будет смонтирован в режиме для чтения (ReadOnly). Если образ является ISO-образом, он будет смонтирован как устройство CDROM. Образ с хранилищем Kubernetes будет смонтирован как эфемерный диск, поэтому изменения в томе будут потеряны при перезагрузке. - properties: - name: - description: | - Имя ресурса `VirtualMachineImage`. - virtualMachineDisk: - description: | - Подключить `VirtualMachineDisk` в качестве дискового устройства в режиме RW. - properties: - name: - description: | - Имя ресурса `VirtualMachineDisk`. + Имя ресурса. restartApprovalID: description: | Хэш изменений виртуальной машины из .status.changeID. @@ -526,7 +521,7 @@ spec: ipAddress: description: | IP-адрес ВМ. - blockDevicesAttached: + blockDeviceRefs: description: | Список блочных устройств, подключенных к ВМ. items: @@ -534,24 +529,12 @@ spec: hotpluggable: description: | Блочное устройство доступно для горячего подключения. - type: + kind: description: | Тип блочного устройства. - clusterVirtualMachineImage: - properties: - name: - description: | - Имя существующего ресурса `ClusterVirtualMachineImage`. - virtualMachineImage: - properties: - name: - description: | - Имя существующего ресурса `VirtualMachineImage`. - virtualMachineDisk: - properties: - name: - description: | - Имя существующего ресурса `VirtualMachineDisk`. + name: + description: | + Имя существующего ресурса. target: description: | Название подключенного блочного устройства. diff --git a/crds/doc-ru-virtualmachineblockdeviceattachment.yaml b/crds/doc-ru-virtualmachineblockdeviceattachment.yaml index 1d68a5864..7d62f03f2 100644 --- a/crds/doc-ru-virtualmachineblockdeviceattachment.yaml +++ b/crds/doc-ru-virtualmachineblockdeviceattachment.yaml @@ -8,30 +8,24 @@ spec: properties: spec: properties: - virtualMachineName: + virtualMachine: description: | Имя виртуальной машины, к которой подключен диск. - blockDevice: + blockDeviceRef: description: | Блочное устройство, которое будет подключено к ВМ в качестве диска hotPlug. properties: - type: + kind: description: | Тип блочного устройства. Возможны следующие варианты: - * `VirtualMachineDisk` — использовать `VirtualMachineDisk` в качестве диска. Этот тип всегда монтируется в режиме RW. - virtualMachineDisk: + * `VirtualDisk` — использовать `VirtualDisk` в качестве диска. Этот тип всегда монтируется в режиме RW. + name: description: | - Использовать `VirtualMachineDisk` в качестве диска. Этот тип всегда монтируется в режиме RW. - required: - - name - properties: - name: - description: | - Имя существующего ресурса `VirtualMachineDisk` + Имя блочного устройства status: properties: - virtualMachineName: + virtualMachine: description: | Имя виртуальной машины, к которой подключен этот диск. phase: diff --git a/crds/doc-ru-virtualmachineipaddressclaim.yaml b/crds/doc-ru-virtualmachineipaddressclaim.yaml index 8560d489d..5463e8d58 100644 --- a/crds/doc-ru-virtualmachineipaddressclaim.yaml +++ b/crds/doc-ru-virtualmachineipaddressclaim.yaml @@ -13,7 +13,7 @@ spec: address: description: | Запрашиваемый IP-адрес. Если это значение не задано, будет назначен следующий доступный IP-адрес. - leaseName: + virtualMachineIPAddressLease: description: | Выданный `VirtualMachineIPAddressLease`, управляется автоматически. reclaimPolicy: @@ -30,12 +30,17 @@ spec: address: description: | Назначенный IP-адрес. - virtualMachineName: + virtualMachine: description: | Имя виртуальной машины, которая в настоящее время использует этот IP-адрес. phase: description: | - Текущее состояние ресурса. + Представляет текущее состояние ресурса `VirtualMachineIPAddressClaim`. + + * Pending - создание ресурса находится в процессе выполнения. + * Bound - ресурс `VirtualMachineIPAddressClaim` привязан к ресурсу `VirtualMachineIPAddressLease`. + * Lost - ресурс `VirtualMachineIPAddressClaim` потерял свойю связку с `VirtualMachineIPAddressLease`. + * Conflict - `VirtualMachineIPAddressLease` уже привязан к другом ресурсу `VirtualMachineIPAddressClaim`. conflictMessage: description: | Подробное описание ошибки. diff --git a/crds/doc-ru-virtualmachineipaddresslease.yaml b/crds/doc-ru-virtualmachineipaddresslease.yaml index 9b229c322..924337f14 100644 --- a/crds/doc-ru-virtualmachineipaddresslease.yaml +++ b/crds/doc-ru-virtualmachineipaddresslease.yaml @@ -33,4 +33,7 @@ spec: properties: phase: description: | - Представляет текущее состояние выданной аренды IP-адреса. + Представляет текущее состояние ресурса `VirtualMachineIPAddressLease`. + + * Bound - ресурс `VirtualMachineIPAddressLease` привязан к ресурсу `VirtualMachineIPAddressClaim`. + * Released - ресурс `VirtualMachineIPAddressLease` доступен для связки с новым ресурсом `VirtualMachineIPAddressClaim`. diff --git a/crds/doc-ru-virtualmachineoperations.yaml b/crds/doc-ru-virtualmachineoperation.yaml similarity index 98% rename from crds/doc-ru-virtualmachineoperations.yaml rename to crds/doc-ru-virtualmachineoperation.yaml index 2cf2e8c4b..05dbfdd1e 100644 --- a/crds/doc-ru-virtualmachineoperations.yaml +++ b/crds/doc-ru-virtualmachineoperation.yaml @@ -15,7 +15,7 @@ spec: * Start - запустить виртуальную машину. * Stop - остановить виртуальную машину. * Restart - перезапустить виртуальную машину. - virtualMachineName: + virtualMachine: description: | Имя виртуальной машины, для которой выполняется операция. force: diff --git a/crds/embedded/cdi.yaml b/crds/embedded/cdi.yaml index 1f1de8316..af3ef6f6d 100644 --- a/crds/embedded/cdi.yaml +++ b/crds/embedded/cdi.yaml @@ -3,17 +3,19 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.13.0 - name: cdis.x.virtualization.deckhouse.io + name: dvpinternalcdis.internal.virtualization.deckhouse.io spec: - group: x.virtualization.deckhouse.io + group: internal.virtualization.deckhouse.io names: - kind: CDI - listKind: CDIList - plural: cdis + categories: + - dvpinternal + kind: DVPInternalCDI + listKind: DVPInternalCDIList + plural: dvpinternalcdis shortNames: - - xcdi - - xcdis - singular: cdi + - dvpcdi + - dvpcdis + singular: dvpinternalcdi scope: Cluster versions: - additionalPrinterColumns: diff --git a/crds/embedded/kubevirt.yaml b/crds/embedded/kubevirt.yaml index ec52253f0..5ced54ae6 100644 --- a/crds/embedded/kubevirt.yaml +++ b/crds/embedded/kubevirt.yaml @@ -1,25 +1,28 @@ # Source: # https://github.com/kubevirt/kubevirt/releases/download/v1.0.0/kubevirt-operator.yaml # Changes: +# - 2024.04.16 +# - Add prefixes xinternal, XInternal # - 2023.12.12 # - Add x.virtualization.deckhouse prefix # - Remove short names. # - Remove all category, add kubevirt category. + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: operator.kubevirt.io: "" - name: kubevirts.x.virtualization.deckhouse.io + name: dvpinternalkubevirts.internal.virtualization.deckhouse.io spec: - group: x.virtualization.deckhouse.io + group: internal.virtualization.deckhouse.io names: categories: - - kubevirt - kind: KubeVirt - plural: kubevirts - singular: kubevirt + - dvpinternal + kind: DVPInternalKubeVirt + plural: dvpinternalkubevirts + singular: dvpinternalkubevirt scope: Namespaced versions: - additionalPrinterColumns: diff --git a/crds/virtualmachinedisk.yaml b/crds/virtualdisk.yaml similarity index 85% rename from crds/virtualmachinedisk.yaml rename to crds/virtualdisk.yaml index eed5ad2df..ac7d8f18f 100644 --- a/crds/virtualmachinedisk.yaml +++ b/crds/virtualdisk.yaml @@ -1,7 +1,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: virtualmachinedisks.virtualization.deckhouse.io + name: virtualdisks.virtualization.deckhouse.io labels: heritage: deckhouse module: virtualization @@ -12,12 +12,12 @@ spec: categories: - all - virtualization - plural: virtualmachinedisks - singular: virtualmachinedisk - kind: VirtualMachineDisk + plural: virtualdisks + singular: virtualdisk + kind: VirtualDisk shortNames: - - vmd - - vmds + - vd + - vds preserveUnknownFields: false versions: - name: v1alpha2 @@ -27,7 +27,7 @@ spec: openAPIV3Schema: type: object description: | - Describes a virtual machine disk that can be mounted in `VirtualMachines`. Once the resource is created, only the disk size `.spec.persistentVolumeClaim.size` can be changed, all other fields are immutable. + Describes a virtual disk that can be mounted in `Virtuals`. Once the resource is created, only the disk size `.spec.persistentVolumeClaim.size` can be changed, all other fields are immutable. A PVC is created under the hood of the resource, into which the data from the source is filled. required: @@ -48,7 +48,7 @@ spec: description: | Desired size for PVC to store the disk. If the disk is created from an image, the size must be at least as large as the original unpacked image. pattern: "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$" - storageClassName: + storageClass: type: string description: | The name of the StorageClass required by the claim. More info — https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 @@ -64,16 +64,14 @@ spec: enum: - "HTTP" - "ContainerImage" - - "VirtualMachineImage" - - "ClusterVirtualMachineImage" + - "ObjectRef" - "Upload" description: | The type of an origin of the disk. 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. - * `VirtualMachineImage` — fill the disk from another existing `VirtualMachineImage`. - * `ClusterVirtualMachineImage` — fill the disk from another existing `ClusterVirtualMachineImage`. + * `ObjectRef` — fill the disk from another existing `VirtualImage` or `ClusterVirtualImage`. * `Upload` — fill the disk with data, uploaded by user via the special interface. http: type: object @@ -162,28 +160,21 @@ spec: The CA chain in base64 format to verify the container registry. example: | YWFhCg== - virtualMachineImage: + objectRef: type: object - description: | - Use another existing `VirtualMachineImage`. - required: - - name + description: Reference to existing `VirtualImage` or `ClusterVirtualImage`. + required: ["kind", "name"] properties: - name: + kind: type: string - description: | - A name of existing `VirtualMachineImage`. - clusterVirtualMachineImage: - type: object - description: | - Use another existing `ClusterVirtualMachineImage`. - required: - - name - properties: + description: A kind of existing `VirtualImage` or `ClusterVirtualImage`. + enum: + - "ClusterVirtualImage" + - "VirtualImage" name: type: string description: | - A name of existing `ClusterVirtualMachineImage`. + A name of existing `VirtualImage` or `ClusterVirtualImage`. oneOf: - properties: type: @@ -197,14 +188,9 @@ spec: required: ["containerImage"] - properties: type: - enum: ["VirtualMachineImage"] - virtualMachineImage: {} - required: ["virtualMachineImage"] - - properties: - type: - enum: ["ClusterVirtualMachineImage"] - clusterVirtualMachineImage: {} - required: ["clusterVirtualMachineImage"] + enum: ["ObjectRef"] + objectRef: {} + required: ["objectRef"] - properties: type: enum: ["Upload"] @@ -246,14 +232,14 @@ spec: target: type: object properties: - persistentVolumeClaimName: + persistentVolumeClaim: type: string description: | Created PersistentVolumeClaim name for Kubernetes storage. phase: type: string description: | - Current status of `VirtualMachineDisk` resource: + Current status of `VirtualDisk` resource: * Pending - The resource has been created and is on a waiting queue. * Provisioning - The process of resource creation (copying/downloading/filling the PVC with data/extending PVC) is in progress. * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. @@ -289,7 +275,7 @@ spec: usedInVMs: type: array description: | - A list of virtual machines that use the disk + A list of virtual that use the disk example: [{ name: "VM100" }, { name: "VM200" }] items: type: object @@ -308,7 +294,7 @@ spec: jsonPath: .status.progress priority: 1 - name: Target PVC - jsonPath: .status.target.persistentVolumeClaimName + jsonPath: .status.target.persistentVolumeClaim type: string priority: 1 - name: Age diff --git a/crds/virtualmachineimage.yaml b/crds/virtualimage.yaml similarity index 86% rename from crds/virtualmachineimage.yaml rename to crds/virtualimage.yaml index 5fe1a545c..d83809163 100644 --- a/crds/virtualmachineimage.yaml +++ b/crds/virtualimage.yaml @@ -1,7 +1,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: virtualmachineimages.virtualization.deckhouse.io + name: virtualimages.virtualization.deckhouse.io labels: heritage: deckhouse module: virtualization @@ -12,12 +12,12 @@ spec: categories: - all - virtualization - plural: virtualmachineimages - singular: virtualmachineimage - kind: VirtualMachineImage + plural: virtualimages + singular: virtualimage + kind: VirtualImage shortNames: - - vmi - - vmis + - vi + - vis preserveUnknownFields: false versions: - name: v1alpha2 @@ -27,7 +27,7 @@ spec: openAPIV3Schema: type: object description: | - This resource describes a virtual machine disk image or installation image (iso) that can be used as a data source for new `VirtualMachineDisks` or can be mounted in `VirtualMachines`. + 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. @@ -61,16 +61,14 @@ spec: enum: - "HTTP" - "ContainerImage" - - "VirtualMachineImage" - - "ClusterVirtualMachineImage" + - "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. - * `VirtualMachineImage` — create an image from another existing `VirtualMachineImage`. - * `ClusterVirtualMachineImage` — create an image from another existing `ClusterVirtualMachineImage`. + * `ObjectRef` — fill the disk from another existing `VirtualImage` or `ClusterVirtualImage`. * `Upload` — fill the image with data, uploaded by user via the special interface. http: type: object @@ -158,28 +156,21 @@ spec: The CA chain in base64 format to verify the container registry. example: | YWFhCg== - virtualMachineImage: + objectRef: type: object - description: | - Use another existing `VirtualMachineImage`. - required: - - name + description: Reference to existing `VirtualImage` or `ClusterVirtualImage`. + required: ["kind", "name"] properties: - name: + kind: type: string - description: | - A name of existing `VirtualMachineImage`. - clusterVirtualMachineImage: - type: object - description: | - Use another existing `ClusterVirtualMachineImage`. - required: - - name - properties: + description: A kind of existing `VirtualImage` or `ClusterVirtualImage`. + enum: + - "ClusterVirtualImage" + - "VirtualImage" name: type: string description: | - A name of existing `ClusterVirtualMachineImage`. + A name of existing `VirtualImage` or `ClusterVirtualImage`. oneOf: - properties: type: @@ -193,14 +184,9 @@ spec: required: ["containerImage"] - properties: type: - enum: ["VirtualMachineImage"] - virtualMachineImage: {} - required: ["virtualMachineImage"] - - properties: - type: - enum: ["ClusterVirtualMachineImage"] - clusterVirtualMachineImage: {} - required: ["clusterVirtualMachineImage"] + enum: ["ObjectRef"] + objectRef: {} + required: ["objectRef"] - properties: type: enum: ["Upload"] @@ -279,13 +265,13 @@ spec: properties: registryURL: type: string - example: dvcr.svc./cvmi/:latest + example: dvcr..svc/vi//:latest description: | Created image in DVCR. phase: type: string description: | - Current status of `VirtualMachineImage` resource: + Current status of `VirtualImage` 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. @@ -324,7 +310,7 @@ spec: usedInVMs: type: array description: | - A list of virtual machines that use the image + A list of virtual that use the image example: [{ name: "VM100" }, { name: "VM200" }] items: type: object diff --git a/crds/virtualmachine.yaml b/crds/virtualmachine.yaml index 6757eada8..a942b04b9 100644 --- a/crds/virtualmachine.yaml +++ b/crds/virtualmachine.yaml @@ -37,7 +37,7 @@ spec: required: - cpu - memory - - blockDevices + - blockDeviceRefs properties: provisioning: description: | @@ -48,67 +48,80 @@ spec: description: | This parameter defines the type of provisioning script: - * SysprepSecret - allows to automate Windows installation, setup, and custom software provisioning. - * UserData - allows the use of inline cloud-init userdata in the .spec.provisioning.UserData section. - * UserDataSecret - allows the use of an existing Secret with cloud-init userdata. + * UserDataRef - allows tto automate OS installation with cloud-init userdata. + + * SysprepRef - allows to automate Windows installation, setup, and custom software provisioning. More information: https://cloudinit.readthedocs.io/en/latest/reference/examples.html type: string enum: - - SysprepSecret - UserData - - UserDataSecret - sysprepSecretRef: + - UserDataRef + - SysprepRef + userData: description: | - Reference to an existing Secret with a Windows sysprep automation. + Inline cloud-init userdata script. + type: string + userDataRef: + description: | + Reference to an existing Secret with a cloud-init userdata script. type: object properties: + kind: + description: The kind of an existing Windows sysprep automation. + default: "Secret" + type: string + enum: + - Secret name: type: string description: | Secret name. - required: ["name"] - userData: + required: ["name", "kind"] + sysprepRef: description: | - Inline cloud-init userdata script. - type: string - userDataSecretRef: - description: | - Reference to an existing Secret with a cloud-init userdata script. + Reference to an existing Windows sysprep automation. type: object properties: + kind: + description: The kind of an existing Windows sysprep automation. + default: "Secret" + type: string + enum: + - Secret name: type: string description: | Secret name. - required: ["name"] + required: ["kind", "name"] oneOf: - properties: type: - enum: ["SysprepSecret"] - required: ["sysprepSecretRef"] + enum: ["Sysprep"] + sysprepRef: {} + required: ["sysprepRef"] not: anyOf: - required: ["userData"] - - required: ["userDataSecretRef"] + - required: ["userDataRef"] - properties: type: enum: ["UserData"] required: ["userData"] not: anyOf: - - required: ["sysprepSecretRef"] - - required: ["userDataSecretRef"] + - required: ["sysprepRef"] + - required: ["userDataRef"] - properties: type: - enum: ["UserDataSecret"] - userDataSecretRef: {} - required: ["userDataSecretRef"] + enum: ["UserDataRef"] + userDataRef: {} + required: ["userDataRef"] not: anyOf: - - required: ["sysprepSecretRef"] + - required: ["sysprepRef"] - required: ["userData"] runPolicy: type: string @@ -126,7 +139,7 @@ spec: * `Manual` - after creation the VM is switched off, the VM state (switching on/off) is controlled via sub-resources or OS means. * `AlwaysOnUnlessStoppedManually` - after creation the VM is always in a running state, even in case of its shutdown by means of the OS, the VM can be shut down using the corresponding subresource. - virtualMachineIPAddressClaimName: + virtualMachineIPAddressClaim: type: string description: | The name for associated `VirtualMachineIPAddressClaim` resource. @@ -835,7 +848,7 @@ spec: required: - cores properties: - modelName: + virtualMachineCPUModel: type: string default: "generic-v1" description: | @@ -866,87 +879,32 @@ spec: description: | Describes the maximum amount of memory resources allowed. - blockDevices: + blockDeviceRefs: type: array description: | - List of block devices that can be mounted by disks belonging to the VM. + List of block devices that can be mounted by disks belonging to the virtual machine. The order of booting is determined by the order in the list. items: type: object + description: | + The reference to block device. properties: - type: + kind: type: string - enum: - - "ClusterVirtualMachineImage" - - "VirtualMachineImage" - - "VirtualMachineDisk" description: | The type of the block device. Options are: - * `ClusterVirtualMachineImage` — Use `ClusterVirtualMachineImage` as the disk. This type is always mounted in RO mode. If the image is an iso-image, it will be mounted as a CDROM device. - * `VirtualMachineImage` — Use `VirtualMachineImage` as the disk. This type is always mounted in RO mode. If the image is an iso-image, it will be mounted as a CDROM device. - * `VirtualMachineDisk` — Use `VirtualMachineDisk` as the disk. This type is always mounted in RW mode. - clusterVirtualMachineImage: - type: object - description: | - Attach `ClusterVirtualMachineImage` as the disk in RO mode. If the image is an iso-image, it will be mounted as a CDROM device. - required: - - name - properties: - name: - type: string - description: | - The name of the `ClusterVirtualMachineImage` resource. - virtualMachineImage: - type: object - description: | - Use `VirtualMachineImage` as the disk. The image with storage ContainerRegistry will be mounted in RO mode. If the image is an iso-image, it will be mounted as a CDROM device. The image with storage Kubernetes will be mounted as ephemeral disk, so changes to volume will be lost on reboot. - required: - - name - properties: - name: - type: string - description: | - The name of the `VirtualMachineImage` resource. - virtualMachineDisk: - type: object + * `ClusterVirtualImage` — Use `ClusterVirtualImage` as the disk. This type is always mounted in RO mode. If the image is an iso-image, it will be mounted as a CDROM device. + * `VirtualImage` — Use `VirtualImage` as the disk. This type is always mounted in RO mode. If the image is an iso-image, it will be mounted as a CDROM device. + * `VirtualDisk` — Use `VirtualDisk` as the disk. This type is always mounted in RW mode. + enum: + - "ClusterVirtualImage" + - "VirtualImage" + - "VirtualDisk" + name: + type: string description: | - Attach `VirtualMachineDisk` as the disk device in RW mode. - required: - - name - properties: - name: - type: string - description: | - The name of the `VirtualMachineDisk` resource. - oneOf: - - properties: - type: - enum: ["ClusterVirtualMachineImage"] - clusterVirtualMachineImage: {} - required: ["clusterVirtualMachineImage"] - not: - anyOf: - - required: ["virtualMachineImage"] - - required: ["virtualMachineDisk"] - - properties: - type: - enum: ["VirtualMachineImage"] - virtualMachineImage: {} - required: ["virtualMachineImage"] - not: - anyOf: - - required: ["clusterVirtualMachineImage"] - - required: ["virtualMachineDisk"] - - properties: - type: - enum: ["VirtualMachineDisk"] - virtualMachineDisk: {} - required: ["virtualMachineDisk"] - not: - anyOf: - - required: ["virtualMachineImage"] - - required: ["clusterVirtualMachineImage"] + The name of attached resource. status: type: object properties: @@ -978,11 +936,11 @@ spec: - "Starting" - "Migrating" - "Pause" - nodeName: + node: type: string description: | The name of the node on which the VM is currently running. - ipAddressClaim: + virtualMachineIPAddressClaim: type: string description: | Name of `VirtualMachineIPAddressClaim` holding the ip address of the VirtualMachine. @@ -990,74 +948,29 @@ spec: type: string description: | IP address of VM. - blockDevicesAttached: + blockDeviceRefs: type: array description: | - The list of attached block devices. + The list of attached block device attachments. items: type: object - required: ["type", "size"] - oneOf: - - properties: - type: - enum: ["ClusterVirtualMachineImage"] - clusterVirtualMachineImage: {} - required: ["clusterVirtualMachineImage"] - not: - anyOf: - - required: ["virtualMachineImage"] - - required: ["virtualMachineDisk"] - - properties: - type: - enum: ["VirtualMachineImage"] - virtualMachineImage: {} - required: ["virtualMachineImage"] - not: - anyOf: - - required: ["clusterVirtualMachineImage"] - - required: ["virtualMachineDisk"] - - properties: - type: - enum: ["VirtualMachineDisk"] - virtualMachineDisk: {} - required: ["virtualMachineDisk"] - not: - anyOf: - - required: ["virtualMachineImage"] - - required: ["clusterVirtualMachineImage"] + required: ["kind", "name", "size"] properties: hotpluggable: type: boolean description: | Block device is available for hot plug. - type: + kind: type: string description: The type of block device. enum: - - "ClusterVirtualMachineImage" - - "VirtualMachineImage" - - "VirtualMachineDisk" - clusterVirtualMachineImage: - type: object - properties: - name: - type: string - description: | - The name of `ClusterVirtualMachineImage` resource. - virtualMachineImage: - type: object - properties: - name: - type: string - description: | - The name of `VirtualMachineImage` resource. - virtualMachineDisk: - type: object - properties: - name: - type: string - description: | - The name of `VirtualMachineDisk` resource. + - "ClusterVirtualImage" + - "VirtualImage" + - "VirtualDisk" + name: + type: string + description: | + The name of attached resource. target: type: string description: The name of attached block device. @@ -1113,9 +1026,9 @@ spec: - name: Phase type: string jsonPath: .status.phase - - name: NodeName + - name: Node type: string - jsonPath: .status.nodeName + jsonPath: .status.node - name: IPAddress type: string jsonPath: .status.ipAddress diff --git a/crds/virtualmachineblockdeviceattachment.yaml b/crds/virtualmachineblockdeviceattachment.yaml index 959473436..f1ded4d6b 100644 --- a/crds/virtualmachineblockdeviceattachment.yaml +++ b/crds/virtualmachineblockdeviceattachment.yaml @@ -35,44 +35,35 @@ spec: spec: type: object required: - - virtualMachineName - - blockDevice + - virtualMachine + - blockDeviceRef properties: - virtualMachineName: + virtualMachine: type: string description: | The name of the virtual machine to which the disk or image is connected. - blockDevice: + blockDeviceRef: type: object description: | The block device that will be connected as a hot plug disk to the virtual machine. + + required: ["kind", "name"] properties: - type: + kind: type: string enum: - - "VirtualMachineDisk" + - "VirtualDisk" description: | The type of the block device. Options are: - * `VirtualMachineDisk` — Use `VirtualMachineDisk` as the disk. This type is always mounted in RW mode. - virtualMachineDisk: - type: object - description: Use `VirtualMachineDisk` as the disk. This type is always mounted in RW mode. - required: - - name - properties: - name: - type: string - description: The name of `VirtualMachineDisk` - oneOf: - - properties: - type: - enum: ["VirtualMachineDisk"] - virtualMachineDisk: {} + * `VirtualDisk` — Use `VirtualDisk` as the disk. This type is always mounted in RW mode. + name: + type: string + description: The name of block device to attach. status: type: object properties: - virtualMachineName: + virtualMachine: type: string description: | The name of the virtual machine to which this disk is attached. @@ -100,9 +91,9 @@ spec: - name: Phase type: string jsonPath: .status.phase - - name: VirtualMachineName + - name: VirtualMachine type: string - jsonPath: .status.virtualMachineName + jsonPath: .status.virtualMachine priority: 1 - name: FailureReason type: string diff --git a/crds/virtualmachinecpumodel.yaml b/crds/virtualmachinecpumodel.yaml index 97780f2ca..08cc9218a 100644 --- a/crds/virtualmachinecpumodel.yaml +++ b/crds/virtualmachinecpumodel.yaml @@ -63,13 +63,13 @@ spec: properties: phase: type: string + enum: ["Pending", "InProgress", "Ready", "Failed"] description: | Current status of `VirtualMachineCPUModel` resource: * Pending - the resource is in the queue for processing. * InProgress - the resource is in the process of being created. * Ready - the resource has been created successfully. * Failed - an error occurred during the resource creation process. - enum: ["Pending", "InProgress", "Ready", "Failed"] features: type: object description: | diff --git a/crds/virtualmachineipaddressclaim.yaml b/crds/virtualmachineipaddressclaim.yaml index 76d2b2a91..39e0b3adf 100644 --- a/crds/virtualmachineipaddressclaim.yaml +++ b/crds/virtualmachineipaddressclaim.yaml @@ -39,7 +39,7 @@ spec: description: | The requested IP address. If omitted the next available IP address will be assigned. type: string - leaseName: + virtualMachineIPAddressLease: description: | The issued `VirtualMachineIPAddressLease`, managed automatically. type: string @@ -61,14 +61,24 @@ spec: description: | The assigned IP address. type: string - virtualMachineName: + virtualMachine: description: | Represents the virtual machine that currently uses this IP address. type: string phase: - description: | - The current state of the resource. type: string + enum: + - "Pending" + - "Bound" + - "Lost" + - "Conflict" + description: | + Represents the current state of IP address claim. + + * Pending - the process of creating is in progress. + * Bound - the IP address claim is bound to IP address lease. + * Lost - the IP address claim has lost its IP address lease. + * Conflict - the IP address lease is bound to another claim. conflictMessage: description: | Detailed description of the error. @@ -86,7 +96,7 @@ spec: - jsonPath: .status.phase name: Status type: string - - jsonPath: .status.virtualMachineName + - jsonPath: .status.virtualMachine name: VM type: string - jsonPath: .metadata.creationTimestamp diff --git a/crds/virtualmachineipaddresslease.yaml b/crds/virtualmachineipaddresslease.yaml index 8a52b8616..ae1ac7ae5 100644 --- a/crds/virtualmachineipaddresslease.yaml +++ b/crds/virtualmachineipaddresslease.yaml @@ -61,14 +61,20 @@ spec: type: object type: object status: + type: object description: | The observed state of `VirtualMachineIPAddressLease`. properties: phase: + type: string + enum: + - "Bound" + - "Released" description: | Represents the current state of issued IP address lease. - type: string - type: object + + * Bound - the IP address lease is bound to IP address claim. + * Released - the IP address lease is available for binding. type: object served: true storage: true diff --git a/crds/virtualmachineoperations.yaml b/crds/virtualmachineoperation.yaml similarity index 93% rename from crds/virtualmachineoperations.yaml rename to crds/virtualmachineoperation.yaml index f8faa9275..8fdd87c47 100644 --- a/crds/virtualmachineoperations.yaml +++ b/crds/virtualmachineoperation.yaml @@ -32,7 +32,7 @@ spec: spec: type: object required: - - virtualMachineName + - virtualMachine properties: type: type: string @@ -42,7 +42,7 @@ spec: * Start - start the virtualmachine. * Stop - stop the virtualmachine. * Restart - restart the virtualmachine. - virtualMachineName: + virtualMachine: type: string description: | The name of the virtual machine for which the operation is performed. @@ -54,7 +54,7 @@ spec: - properties: type: enum: ["Start"] - required: ["virtualMachineName"] + required: ["virtualMachine"] not: anyOf: - required: @@ -62,7 +62,7 @@ spec: - properties: type: enum: ["Restart", "Stop"] - required: ["virtualMachineName"] + required: ["virtualMachine"] status: type: object properties: @@ -92,8 +92,8 @@ spec: - name: Phase type: string jsonPath: .status.phase - - name: VMName - jsonPath: .spec.virtualMachineName + - name: VM + jsonPath: .spec.virtualMachine type: string - name: Age type: date diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 543ca2678..7ef97700f 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -12,30 +12,30 @@ Let's create namespace where we will create virtual machines: kubectl create ns vms ``` -Let's create a virtual machine disk from an external source: +Let's create a virtual disk from an external source: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: linux-disk namespace: vms spec: persistentVolumeClaim: size: 10Gi - storageClassName: local-path + storageClass: local-path dataSource: type: HTTP http: url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img" ``` -After creating `VirtualMachineDiks` in the namespace vms, the pod `importer-*` will start, which will perform the download of the given image. +After creating `VirtualDisk` in the namespace vms, the pod `importer-*` will start, which will perform the download of the given image. Let's look at the current status of the resource: ```bash -kubectl -n vms get virtualmachinedisk -o wide +kubectl -n vms get virtualdisk -o wide # NAME PHASE CAPACITY PROGRESS TARGET PVC AGE # linux-disk Ready 10Gi 100% vmd-vmd-blank-001-10c7616b-ba9c-4531-9874-ebcb3a2d83ad 1m @@ -74,10 +74,9 @@ spec: lock_passwd: false ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTXjTmx3hq2EPDQHWSJN7By1VNFZ8colI5tEeZDBVYAe9Oxq4FZsKCb1aGIskDaiAHTxrbd2efoJTcPQLBSBM79dcELtqfKj9dtjy4S1W0mydvWb2oWLnvOaZX/H6pqjz8jrJAKXwXj2pWCOzXerwk9oSI4fCE7VbqsfT4bBfv27FN4/Vqa6iWiCc71oJopL9DldtuIYDVUgOZOa+t2J4hPCCSqEJK/r+ToHQbOWxbC5/OAufXDw2W1vkVeaZUur5xwwAxIb3wM3WoS3BbwNlDYg9UB2D8+EZgNz1CCCpSy1ELIn7q8RnrTp0+H8V9LoWHSgh3VCWeW8C/MnTW90IR - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: linux-disk + blockDeviceRefs: + - type: VirtualDisk + name: linux-disk ``` Let's check that the virtual machine is created and running: @@ -85,7 +84,7 @@ Let's check that the virtual machine is created and running: ```bash kubectl -n default get virtualmachine -# NAME PHASE NODENAME IPADDRESS AGE +# NAME PHASE NODE IPADDRESS AGE # linux-vm Running virtlab-1 10.66.10.1 5m ``` @@ -105,17 +104,17 @@ After running the command, the default VNC client will start. An alternative way # Images -`VirtualMachineImage` and `ClusterVirtualMachineImage` are intended to store virtual machine disk images or installation images in `iso` format to create and replicate virtual machine disks in the same way. When connected to a virtual machine, these images are read-only and the `iso` format installation image will be attached as a cdrom device. +`VirtualImage` and `ClusterVirtualImage` are intended to store virtual machine disk images or installation images in `iso` format to create and replicate virtual machine disks in the same way. When connected to a virtual machine, these images are read-only and the `iso` format installation image will be attached as a cdrom device. -The `VirtualMachineImage` resource is only available in the namespace in which it was created, while `ClusterVirtualMachineImage` is available for all namespaces within the cluster. +The `VirtualImage` resource is only available in the namespace in which it was created, while `ClusterVirtualImage` is available for all namespaces within the cluster. -Depending on the configuration, the `VirtualMachineImage` resource can store data in `DVCR` or use platform-provided disk storage (PV). On the other hand, `ClusterVirtualMachineImage` stores data only in `DVCR`, providing a single access to all images for all namespaces in the cluster. +Depending on the configuration, the `VirtualImage` resource can store data in `DVCR` or use platform-provided disk storage (PV). On the other hand, `ClusterVirtualImage` stores data only in `DVCR`, providing a single access to all images for all namespaces in the cluster. Let's look at the creation of these resources with examples: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: ubuntu-img namespace: vms @@ -130,17 +129,17 @@ spec: Let's see what happens: ```bash -kubectl -n vms get virtualmachineimage +kubectl -n vms get virtualimage # NAME PHASE CDROM PROGRESS AGE # ubuntu-img Ready false 100% 10m ``` -The `ClusterVirtualMachineImage` resource is created similarly, but does not require the `storage` settings to be specified: +The `ClusterVirtualImage` resource is created similarly, but does not require the `storage` settings to be specified: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: ubuntu-img spec: @@ -150,10 +149,10 @@ spec: url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img" ``` -Let's look at the status of `ClusterVirtualMachineImage`: +Let's look at the status of `ClusterVirtualImage`: ```bash -kubectl get clustervirtualmachineimage +kubectl get clustervirtualimage # NAME PHASE CDROM PROGRESS AGE # ubuntu-img Ready false 100% 11m @@ -194,11 +193,11 @@ Upload the created image to the container registry: docker push docker.io/username/ubuntu2204:latest ``` -To use this image, let's create the `ClusterVirtualMachineImage` resource as an example: +To use this image, let's create the `ClusterVirtualImage` resource as an example: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: ubuntu-2204 spec: @@ -211,16 +210,16 @@ spec: To look at a resource and its status, run the command: ```bash -kubectl get clustervirtalmachineimage +kubectl get clustervirtualimage ``` ### Uploading an image from the command line -To upload an image from the command line, we first need to create the following resource, consider `ClusterVirtualMachineImage` as an example: +To upload an image from the command line, we first need to create the following resource, consider `ClusterVirtualImage` as an example: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: some-image spec: @@ -231,7 +230,7 @@ spec: Once the resource is created, let's look at its status: ```bash -kubectl get clustervirtualmachineimages some-image -o json | jq .status.uploadCommand -r +kubectl get clustervirtualimages some-image -o json | jq .status.uploadCommand -r > uploadCommand: curl https://virtualization.example.com/upload/dSJSQW0fSOerjH5ziJo4PEWbnZ4q6ffc -T example.iso @@ -251,7 +250,7 @@ After the `curl` command completes, the image should be created. You can verify that everything was successful by checking the status of the created image: ```bash -kubectl get clustervirtualmachineimages +kubectl get clustervirtualimages # NAME PHASE CDROM PROGRESS AGE # some-image Ready false 100% 10m @@ -275,12 +274,12 @@ The first thing to note is that we can create empty disks! ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vmd-blank spec: persistentVolumeClaim: - storageClassName: "your-storage-class-name" + storageClass: "your-storage-class-name" size: 100M ``` @@ -289,7 +288,7 @@ Once the disk is created, we can use it to connect to the virtual machine. You can view the status of the created resource with the command: ```bash -kubectl get virtualmachinedisk +kubectl get virtualdisk # NAME PHASE CAPACITY AGE # vmd-blank Ready 100Mi 1m @@ -299,22 +298,23 @@ kubectl get virtualmachinedisk We can create disks using existing disk images as well as external sources like images. -When creating a disk resource, we can specify the desired size. If no size is specified, a disk will be created with the size corresponding to the original disk image stored in the `VirtualMachineImage` or `ClusterVirtualMachineImage` resource. If you want to create a larger disk, you must explicitly specify this. +When creating a disk resource, we can specify the desired size. If no size is specified, a disk will be created with the size corresponding to the original disk image stored in the `VirtualImage` or `ClusterVirtualImage` resource. If you want to create a larger disk, you must explicitly specify this. -As an example, we will use a previously created `ClusterVirtualMachineImage` named `ubuntu-2204`: +As an example, we will use a previously created `ClusterVirtualImage` named `ubuntu-2204`: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: ubuntu-root spec: persistentVolumeClaim: size: 10Gi - storageClassName: "your-storage-class-name" + storageClass: "your-storage-class-name" dataSource: - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: + type: ObjectRef + objectRef: + kind: ClusterVirtualImage name: ubuntu-img ``` @@ -336,11 +336,12 @@ kind: VirtualMachineBlockDeviceAttachment metadata: name: vmd-blank-attachment spec: - virtualMachineName: linux-vm # имя виртуальной машины, к которой будет подключен диск + virtualMachine: linux-vm # Name of the virtual machine to attach disk to. blockDevice: - type: VirtualMachineDisk - virtualMachineDisk: - name: vmd-blank # имя подключаемого диска + type: ObjectRef + objectRef: + kind: VirtualDisk + name: vmd-blank # Name of the disk that should be attached. ``` If you change the machine name in this resource to another machine name, the disk will be reconnected from one virtual machine to another. @@ -375,7 +376,7 @@ Let's create a disk for the virtual machine: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: ubuntu-2204-root spec: @@ -423,11 +424,10 @@ spec: cores: 1 memory: size: 2Gi - blockDevices: + blockDeviceRefs: # the order of disks and images in this block determines the boot priority - - type: VirtualMachineDisk - virtualMachineDisk: - name: ubuntu-2204-root + - kind: VirtualDisk + name: ubuntu-2204-root ``` If there is some private data, the initial initial initialization script of the virtual machine can be created in secret. @@ -462,7 +462,7 @@ After startup, the virtual machine must be in `Ready` status. ```bash kubectl get virtualmachine -# NAME PHASE NODENAME IPADDRESS AGE +# NAME PHASE NODE IPADDRESS AGE # linux-vm Running node-name-x 10.66.10.1 5m ``` @@ -486,7 +486,7 @@ spec: ```yaml spec: - virtualMachineIPAddressClaimName: + virtualMachineIPAddressClaim: ``` ### 2. Configuring virtual machine placement rules @@ -511,7 +511,7 @@ After making changes to the machine configuration, nothing will happen because t How can we figure this out? -Let's look at the status of the VM: +Let's look at the status of the virtual machine: ```bash kubectl get linux-vm -o jsonpath='{.status}' @@ -528,7 +528,7 @@ kind: VirtualMachineOperation metadata: name: restart spec: - virtualMachineName: linux-vm + virtualMachine: linux-vm type: Restart EOF ``` @@ -538,7 +538,7 @@ Let's look at the status of the resource that has been created: ```bash kubectl get vmops restart -# NAME PHASE VMNAME AGE +# NAME PHASE VM AGE # restart Completed linux-vm 1m ``` @@ -571,7 +571,7 @@ then look at the status of the virtual machine ```bash kubectl get virtualmachine -# NAME PHASE NODENAME IPADDRESS AGE +# NAME PHASE NODE IPADDRESS AGE # linux-vm Running node-name-x 10.66.10.1 5m ``` diff --git a/docs/EXAMPLES_RU.md b/docs/EXAMPLES_RU.md index 5cded788e..342f32941 100644 --- a/docs/EXAMPLES_RU.md +++ b/docs/EXAMPLES_RU.md @@ -16,26 +16,26 @@ kubectl create ns vms ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: linux-disk namespace: vms spec: persistentVolumeClaim: size: 10Gi - storageClassName: local-path + storageClass: local-path dataSource: type: HTTP http: url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img" ``` -После создания `VirtualMachineDiks` в namespace vms, запустится под с именем `importer-*`, который осуществит загрузку заданного образа. +После создания `VirtualDisk` в namespace vms, запустится под с именем `importer-*`, который осуществит загрузку заданного образа. 3. Посмотрите текущий статус ресурса с помощью команды: ```bash -kubectl -n vms get virtualmachinedisk -o wide +kubectl -n vms get virtualdisk -o wide # NAME PHASE CAPACITY PROGRESS TARGET PVC AGE # linux-disk Ready 10Gi 100% vmd-vmd-blank-001-10c7616b-ba9c-4531-9874-ebcb3a2d83ad 1m @@ -74,10 +74,9 @@ spec: lock_passwd: false ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTXjTmx3hq2EPDQHWSJN7By1VNFZ8colI5tEeZDBVYAe9Oxq4FZsKCb1aGIskDaiAHTxrbd2efoJTcPQLBSBM79dcELtqfKj9dtjy4S1W0mydvWb2oWLnvOaZX/H6pqjz8jrJAKXwXj2pWCOzXerwk9oSI4fCE7VbqsfT4bBfv27FN4/Vqa6iWiCc71oJopL9DldtuIYDVUgOZOa+t2J4hPCCSqEJK/r+ToHQbOWxbC5/OAufXDw2W1vkVeaZUur5xwwAxIb3wM3WoS3BbwNlDYg9UB2D8+EZgNz1CCCpSy1ELIn7q8RnrTp0+H8V9LoWHSgh3VCWeW8C/MnTW90IR - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: linux-disk + blockDeviceRefs: + - kind: VirtualDisk + name: linux-disk ``` 5. Проверьте с помощью команды, что виртуальная машина создана и запущена: @@ -85,7 +84,7 @@ spec: ```bash kubectl -n default get virtualmachine -# NAME PHASE NODENAME IPADDRESS AGE +# NAME PHASE NODE IPADDRESS AGE # linux-vm Running virtlab-1 10.66.10.1 5m ``` @@ -97,24 +96,24 @@ dvp console -n vms linux-vm ## Образы -`VirtualMachineImage` и `ClusterVirtualMachineImage` используются для хранения образов виртуальных машин. +`VirtualImage` и `ClusterVirtualImage` используются для хранения образов виртуальных машин. Образы могут быть следующих видов: - Образ диска виртуальной машины, который предназначен для тиражирования идентичных дисков виртуальных машин. - ISO-образ, содержащий файлы для установки ОС. Этот тип образа подключается к виртуальной машине как cdrom. -Ресурс `VirtualMachineImage` доступен только в том пространстве имен, в котором был создан, а `ClusterVirtualMachineImage` доступен для всех пространств имен внутри кластера. Оба этих ресурсов хранят свои данные в `DVCR`. +Ресурс `VirtualImage` доступен только в том пространстве имен, в котором был создан, а `ClusterVirtualImage` доступен для всех пространств имен внутри кластера. Оба этих ресурсов хранят свои данные в `DVCR`. Образы могут быть получены из различных источников, таких как HTTP-серверы, на которых расположены файлы образов, или контейнерные реестры (container registries), где образы сохраняются и становятся доступны для скачивания. Также существует возможность загрузить образы напрямую из командной строки, используя утилиту `curl`. ### Создание и использование образа c HTTP-ресурса -1. Создайте `VirtualMachineImage`: +1. Создайте `VirtualImage`: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: ubuntu-img namespace: vms @@ -129,17 +128,17 @@ spec: 2. Проверьте результат с помощью команды: ```bash -kubectl -n vms get virtualmachineimage +kubectl -n vms get virtualimage # NAME PHASE CDROM PROGRESS AGE # ubuntu-img Ready false 100% 10m ``` -3. Ресурс `ClusterVirtualMachineImage` создается по аналогии, но не требует указания настроек `storage`: +3. Ресурс `ClusterVirtualImage` создается по аналогии, но не требует указания настроек `storage`: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: ubuntu-img spec: @@ -149,10 +148,10 @@ spec: url: "https://cloud-images.ubuntu.com/minimal/releases/jammy/release-20230615/ubuntu-22.04-minimal-cloudimg-amd64.img" ``` -4. Проверьте статус `ClusterVirtualMachineImage` с помощью команды: +4. Проверьте статус `ClusterVirtualImage` с помощью команды: ```bash -kubectl get clustervirtualmachineimage +kubectl get clustervirtualimage # NAME PHASE CDROM PROGRESS AGE # ubuntu-img Ready false 100% 11m @@ -191,11 +190,11 @@ docker build -t docker.io/username/ubuntu2204:latest docker push docker.io/username/ubuntu2204:latest ``` -- Чтобы использовать этот образ, создайте в качестве примера ресурс `ClusterVirtualMachineImage`: +- Чтобы использовать этот образ, создайте в качестве примера ресурс `ClusterVirtualImage`: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: ubuntu-2204 spec: @@ -208,16 +207,16 @@ spec: - Чтобы посмотреть ресурс и его статус, выполните команду: ```bash -kubectl get clustervirtalmachineimage +kubectl get clustervirtualimage ``` ### Загрузка образа из командной строки -1. Чтобы загрузить образ из командной строки, предварительно создайте следующий ресурс, как представлено ниже на примере `ClusterVirtualMachineImage`: +1. Чтобы загрузить образ из командной строки, предварительно создайте следующий ресурс, как представлено ниже на примере `ClusterVirtualImage`: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: some-image spec: @@ -228,7 +227,7 @@ spec: 2. После того как ресурс будет создан, проверьте его статус с помощью команды: ```bash -kubectl get clustervirtualmachineimages some-image -o json | jq .status.uploadCommand -r +kubectl get clustervirtualimages some-image -o json | jq .status.uploadCommand -r > uploadCommand: curl https://virtualization.example.com/upload/dSJSQW0fSOerjH5ziJo4PEWbnZ4q6ffc -T example.iso @@ -253,7 +252,7 @@ curl https://virtualization.example.com/upload/dSJSQW0fSOerjH5ziJo4PEWbnZ4q6ffc 4. Проверьте, что статус созданного образа `Ready`: ```bash -kubectl get clustervirtualmachineimages +kubectl get clustervirtualimages # NAME PHASE CDROM PROGRESS AGE # some-image Ready false 100% 10m @@ -282,12 +281,12 @@ kubectl get storageclass ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vmd-blank spec: persistentVolumeClaim: - storageClassName: "your-storage-class-name" + storageClass: "your-storage-class-name" size: 100M ``` @@ -296,7 +295,7 @@ spec: 2. Проверьте состояние созданного ресурса с помощью команды: ```bash -kubectl get virtualmachinedisk +kubectl get virtualdisk # NAME PHASE CAPACITY AGE # vmd-blank Ready 100Mi 1m @@ -306,22 +305,23 @@ kubectl get virtualmachinedisk > Можно создать диски из существующих дисковых образов, а также из внешних ресурсов, таких как образы. -При создании ресурса диска можно указать желаемый размер. Если размер не указан, то будет создан диск с размером, соответствующим исходному образу диска, который хранится в ресурсе `VirtualMachineImage` или `ClusterVirtualMachineImage`. Если необходимо создать диск большего размера, укажите необходимый размер. +При создании ресурса диска можно указать желаемый размер. Если размер не указан, то будет создан диск с размером, соответствующим исходному образу диска, который хранится в ресурсе `VirtualImage` или `ClusterVirtualImage`. Если необходимо создать диск большего размера, укажите необходимый размер. -В качестве примера рассмотрен ранее созданный `ClusterVirtualMachineImage` с именем `ubuntu-2204`: +В качестве примера рассмотрен ранее созданный `ClusterVirtualImage` с именем `ubuntu-2204`: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: ubuntu-root spec: persistentVolumeClaim: size: 10Gi - storageClassName: "your-storage-class-name" + storageClass: "your-storage-class-name" dataSource: - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: + type: ObjectRef + objectRef: + kind: ClusterVirtualImage name: ubuntu-img ``` @@ -343,10 +343,10 @@ kind: VirtualMachineBlockDeviceAttachment metadata: name: vmd-blank-attachment spec: - virtualMachineName: linux-vm # Имя виртуальной машины, к которой будет подключен диск. + virtualMachine: linux-vm # Имя виртуальной машины, к которой будет подключен диск. blockDevice: - type: VirtualMachineDisk - virtualMachineDisk: + type: VirtualDisk + virtualDisk: name: vmd-blank # Имя подключаемого диска. ``` @@ -377,7 +377,7 @@ kubectl get virtualmachineblockdeviceattachments ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: ubuntu-2204-root spec: @@ -425,11 +425,10 @@ spec: cores: 1 memory: size: 2Gi - blockDevices: + blockDeviceRefs: # Порядок дисков и образов в данном блоке определяет приоритет загрузки. - - type: VirtualMachineDisk - virtualMachineDisk: - name: ubuntu-2204-root + - kind: VirtualDisk + name: ubuntu-2204-root ``` При наличии приватных данных, сценарий начальной инициализации виртуальной машины может быть создан в Secret'е. Пример Secret'а приведен ниже: @@ -462,7 +461,7 @@ spec: ```bash kubectl get virtualmachine -# NAME PHASE NODENAME IPADDRESS AGE +# NAME PHASE NODE IPADDRESS AGE # linux-vm Running node-name-x 10.66.10.1 5m ``` @@ -486,7 +485,7 @@ spec: ```yaml spec: - virtualMachineIPAddressClaimName: + virtualMachineIPAddressClaim: ``` ### 2. Настройка правил размещения виртуальной машины @@ -528,7 +527,7 @@ kind: VirtualMachineOperation metadata: name: restart-linux-vm spec: - virtualMachineName: linux-vm + virtualMachine: linux-vm type: Restart EOF ``` @@ -538,7 +537,7 @@ EOF ```bash kubectl get vmops restart-linux-vm -# NAME PHASE VMNAME AGE +# NAME PHASE VM AGE # restart-linux-vm Completed linux-vm 1m ``` @@ -571,7 +570,7 @@ cloud@linux-vm$ sudo poweroff ```bash kubectl get virtualmachine -# NAME PHASE NODENAME IPADDRESS AGE +# NAME PHASE NODE IPADDRESS AGE # linux-vm Running node-name-x 10.66.10.1 5m ``` diff --git a/docs/FAQ.md b/docs/FAQ.md index db2a4d360..da9c8ae94 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -12,21 +12,21 @@ Let's create an empty disk for OS installation: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: win-disk namespace: default spec: persistentVolumeClaim: size: 100Gi - storageClassName: local-path + storageClass: local-path ``` Let's create resources with iso-images of Windows OS and virtio drivers: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-11-iso spec: @@ -38,7 +38,7 @@ spec: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-virtio-iso spec: @@ -68,16 +68,13 @@ spec: memory: size: 8Gi enableParavirtualization: true - blockDevices: - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-11-iso - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-virtio-iso - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + blockDeviceRefs: + - kind: ClusterVirtualImage + name: win-11-iso + - kind: ClusterVirtualImage + name: win-virtio-iso + - kind: VirtualDisk + name: win-disk ``` Once the resource is created, the virtual machine will be started. You need to connect to it and use the graphical wizard to add the `virtio` drivers and perform the OS installation. @@ -95,14 +92,13 @@ spec: # ... runPolicy: AlwaysON # ... - blockDevices: - # remove all ClusterVirtualMachineImage resources with iso disks from this section - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + blockDeviceRefs: + # remove all ClusterVirtualImage resources with iso disks from this section + - kind: VirtualDisk + name: win-disk ``` -## How to create a virtual machine image for container registry +## How to create a virtual image for container registry The virtual machine disk image stored in the container registry must be created in a special way. @@ -185,7 +181,7 @@ metadata: ## How to provide windows answer file (Sysprep) -To provide Sysprep ability it's necessary to define in virtual machine with SysprepSecret provisioning. +To provide Sysprep ability it's necessary to define in virtual machine with SysprepRef provisioning. Set answer files (typically named unattend.xml or autounattend.xml) to secret to perform unattended installations of Windows. You can also specify here other files in base64 format (customize.ps1, id_rsa.pub, ...) that you need to successfully execute scripts inside the answer file. @@ -212,8 +208,9 @@ metadata: vm: win spec: provisioning: - type: SysprepSecret - sysprepSecretRef: + type: SysprepRef + sysprepRef: + kind: Secret name: sysprep-config runPolicy: AlwaysOn osType: Windows @@ -224,14 +221,11 @@ spec: memory: size: 8Gi enableParavirtualization: true - blockDevices: - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-11-iso - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-virtio-iso - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + blockDeviceRefs: + - kind: ClusterVirtualImage + name: win-11-iso + - kind: ClusterVirtualImage + name: win-virtio-iso + - kind: VirtualDisk + name: win-disk ``` \ No newline at end of file diff --git a/docs/FAQ_RU.md b/docs/FAQ_RU.md index dca795723..44a577e5b 100644 --- a/docs/FAQ_RU.md +++ b/docs/FAQ_RU.md @@ -12,21 +12,21 @@ title: "FAQ" ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: win-disk namespace: default spec: persistentVolumeClaim: size: 100Gi - storageClassName: local-path + storageClass: local-path ``` 2. Создайте ресурсы с ISO-образами ОС Windows и драйверами virtio: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-11-iso spec: @@ -38,7 +38,7 @@ spec: ```yaml apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-virtio-iso spec: @@ -68,16 +68,13 @@ spec: memory: size: 8Gi enableParavirtualization: true - blockDevices: - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-11-iso - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-virtio-iso - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + blockDeviceRefs: + - kind: ClusterVirtualImage + name: win-11-iso + - kind: ClusterVirtualImage + name: win-virtio-iso + - kind: VirtualDisk + name: win-disk ``` После создания ресурса виртуальная машина будет запущена. К ней необходимо подключиться, и с помощью графического установщика выполнить установку ОС и драйверов `virtio`. @@ -97,11 +94,10 @@ spec: # ... runPolicy: AlwaysON # ... - blockDevices: - # Удалить из блока все ресурсы ClusterVirtualMachineImage с ISO-дисками. - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + blockDeviceRefs: + # Удалить из блока все ресурсы ClusterVirtualImage с ISO-дисками. + - kind: VirtualDisk + name: win-disk ``` 8. После внесенных изменений виртуальная машина запустится, для продолжения работы с ней используйте команду: @@ -199,7 +195,7 @@ metadata: ```shell kubectl get mc virtualization -o jsonpath='{.spec.settings.dvcr.storage.persistentVolumeClaim}' #Output -{"size":"58G","storageClassName":"linstor-thick-data-r1"} +{"size":"58G","storageClass":"linstor-thick-data-r1"} ``` 2. Задайте размер: @@ -217,7 +213,7 @@ moduleconfig.deckhouse.io/virtualization patched ```shell kubectl get mc virtualization -o jsonpath='{.spec.settings.dvcr.storage.persistentVolumeClaim}' #Output -{"size":"59G","storageClassName":"linstor-thick-data-r1"} +{"size":"59G","storageClass":"linstor-thick-data-r1"} kubectl get pvc dvcr -n d8-virtualization #Output @@ -227,7 +223,7 @@ dvcr Bound pvc-6a6cedb8-1292-4440-b789-5cc9d15bbc6b 57617188Ki RWO ## Как предоставить файл ответов windows (Sysprep) -Чтобы предоставить виртуальной машине windows файл ответов необходимо указать provisioning с типом SysprepSecret. +Чтобы предоставить виртуальной машине windows файл ответов необходимо указать provisioning с типом SysprepRef. Прежде всего необходимо создать секрет: @@ -254,8 +250,9 @@ metadata: vm: win spec: provisioning: - type: SysprepSecret - sysprepSecretRef: + type: SysprepRef + sysprepRef: + kind: Secret name: sysprep-config runPolicy: AlwaysOn osType: Windows @@ -266,14 +263,11 @@ spec: memory: size: 8Gi enableParavirtualization: true - blockDevices: - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-11-iso - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-virtio-iso - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + blockDeviceRefs: + - kind: ClusterVirtualImage + name: win-11-iso + - kind: ClusterVirtualImage + name: win-virtio-iso + - kind: VirtualDisk + name: win-disk ``` \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 30d1c6374..117cd506a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -43,12 +43,12 @@ The module includes the following components: The API provides capabilities for creating and managing the following resources: -- Virtual Machine Images -- Virtual Machine Disks +- Virtual Images +- Virtual Disks - Virtual machines - Virtual Machine Operations -### Virtual Machine Images +### Virtual Images Images are immutable resources that allow you to create new virtual machines based on preconfigured and configured images. Depending on the type, images can be in `raw`, `qcow2`, `vmdk` and other formats for virtual machine disk images, and in `iso` format for installation images that can be attached as `cdrom devices`. @@ -56,13 +56,13 @@ You can use external sources such as `http server`, `container registry`, and lo It is important to note that images can be attached to a virtual machine in read-only mode. -Images are of two types: clustered `ClusterVirtualMachineImage`, which are available to all users of the platform, and namespaced `VirtualMachineImage`, which are available only to users within a specific `namespace`. +Images are of two types: clustered `ClusterVirtualImage`, which are available to all users of the platform, and namespaced `VirtualImage`, which are available only to users within a specific `namespace`. -For `ClusterVirtualMachineImage`, images are stored only in `DVCR`, while for `VirtualMachineImage` you can use both `DVCR` and platform-provided storage (`PVC`). +For `ClusterVirtualImage`, images are stored only in `DVCR`, while for `VirtualImage` you can use both `DVCR` and platform-provided storage (`PVC`). -### Virtual Machine Disks +### Virtual Disks -Creating disks for virtual machines is provided by the `VirtualMachineDisk` resource. Disks are used in the virtual machine as the primary storage medium. Disks can be created from external sources, previously created images (`VirtualMachineImage` or `ClusterVirtualMachineImage`) or can be created `empty`. +Creating disks for virtual machines is provided by the `VirtualDisk` resource. Disks are used in the virtual machine as the primary storage medium. Disks can be created from external sources, previously created images (`VirtualImage` or `ClusterVirtualImage`) or can be created `empty`. One of the key features of disks is the ability to resize them without having to stop the virtual machine. It is important to note that only the ability to increase disk size is supported, while decreasing is not available. diff --git a/docs/README_RU.md b/docs/README_RU.md index eec1fdd98..af9964bc8 100644 --- a/docs/README_RU.md +++ b/docs/README_RU.md @@ -61,14 +61,14 @@ API предоставляет возможности для создания и Образы бывают двух типов: -- кластерные `ClusterVirtualMachineImage`, которые доступны для всех пользователей платформы; -- ограниченные по пространству имен `VirtualMachineImage`, которые доступны только для пользователей `namespace`, в котором они созданы. +- кластерные `ClusterVirtualImage`, которые доступны для всех пользователей платформы; +- ограниченные по пространству имен `VirtualImage`, которые доступны только для пользователей `namespace`, в котором они созданы. Все образы хранятся в `DVCR`. ### Диски виртуальных машин -Cоздание дисков для виртуальных машины обеспечивает ресурс `VirtualMachineDisk`. Диски используются в виртуальной машине в качестве основного носителя для хранения данных. Диски могут быть созданы из внешних источников, ранее созданных образов (`VirtualMachineImage` или `ClusterVirtualMachineImage`) или могут быть созданы `пустыми`. +Cоздание дисков для виртуальных машины обеспечивает ресурс `VirtualDisk`. Диски используются в виртуальной машине в качестве основного носителя для хранения данных. Диски могут быть созданы из внешних источников, ранее созданных образов (`VirtualImage` или `ClusterVirtualImage`) или могут быть созданы `пустыми`. Одной из ключевых особенностей дисков является возможность изменения их размера без необходимости остановки виртуальной машины. Важно отметить, что поддерживается только возможность увеличения размера диска, в то время как уменьшение недоступно. diff --git a/docs/images/disks.drawio b/docs/images/disks.drawio index f16c140be..1656ff07c 100644 --- a/docs/images/disks.drawio +++ b/docs/images/disks.drawio @@ -24,13 +24,13 @@ - + - + @@ -39,7 +39,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -74,7 +74,7 @@ - + diff --git a/docs/images/images.drawio b/docs/images/images.drawio index 8e2450363..3953538bf 100644 --- a/docs/images/images.drawio +++ b/docs/images/images.drawio @@ -27,7 +27,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/docs/internal/data_source_details.md b/docs/internal/data_source_details.md index b2bb36b26..22b099233 100644 --- a/docs/internal/data_source_details.md +++ b/docs/internal/data_source_details.md @@ -11,9 +11,9 @@ Additional importer and uploader are implemented to import into DVCR instead PVC - HTTP (equals to http source in DataVolume) - ContainerImage (equals to registry source in DataVolume) - Upload (equals to upload source in DataVolume) -- VirtualMachineImage (import from DVCR) -- ClusterVirtualMachineImage (import from DVCR) -- VirtualMachineDisk (import from DVCR) +- VirtualImage (import from DVCR) +- ClusterVirtualImage (import from DVCR) +- VirtualDisk (import from DVCR) - VirtualMachineDiskSnapshot - not implemented yet - PersistentVolumeClaim - not implemented yet diff --git a/hack/upload-pvc.sh b/hack/upload-pvc.sh index 2fbd3e403..2d47c88dc 100644 --- a/hack/upload-pvc.sh +++ b/hack/upload-pvc.sh @@ -4,7 +4,7 @@ function usage() { cat <WithProxy + + subgraph NoProxy ["`**Original Kubevirt setup**`"] + direction TB + + subgraph np-virt-operator-deploy ["`Deploy/virt-operator`"] + np-virt-operator("`container + name: virt-operator`") + end + + subgraph np-virt-controller-deploy ["`Deploy/virt-controller`"] + np-virt-controller("`container + name: virt-controller`") + end + + np-kube-api["`Kubernetes API Server + with resources in apiGroup + *.kubevirt.io*`"] + + np-virt-operator <-- "Original resources + in API calls" --> np-kube-api + np-virt-controller <-- "Original resources + in API calls" --> np-kube-api + end + subgraph WithProxy ["`**Kubevirt with proxy**`"] + direction TB + + subgraph p-virt-operator-deploy ["`Deploy/virt-operator`"] + p-virt-operator("`container + name: virt-operator`") + p-virt-operator-proxy{{"container + name: proxy"}} + p-virt-operator -- "Original resources + in API calls" --> p-virt-operator-proxy + p-virt-operator-proxy -- "Restored resources + in API responses" --> p-virt-operator + end + + subgraph p-virt-controller-deploy ["`Deploy/virt-controller`"] + p-virt-controller("`container + name: virt-controller`") + p-virt-controller-proxy{{"container + name: proxy"}} + p-virt-controller -- "Original resources +in API calls" --> p-virt-controller-proxy + p-virt-controller-proxy -- "Restored resources + in API responses" --> p-virt-controller + end + + p-kube-api["`Kubernetes API Server + with resources in apiGroup + *.x.virtualization.deckhouse.io*`"] + + p-virt-operator-proxy <-- "Renamed resources in + API calls" --> p-kube-api + p-virt-controller-proxy <-- "Renamed resources in + API calls" --> p-kube-api + end +``` + +All DVP components: +```mermaid +%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart + subgraph kubevirt ["Kubevirt"] + subgraph virt-operator-deploy ["`Deploy/virt-operator`"] + virt-operator("`container: + virt-operator`") + virt-operator-proxy{{"container: + proxy"}} + virt-operator --> virt-operator-proxy + virt-operator-proxy --> virt-operator + end + + subgraph p-virt-controller-deploy ["`Deploy/virt-controller`"] + virt-controller("`container: + virt-controller`") + virt-controller-proxy{{"container: + proxy"}} + virt-controller --> virt-controller-proxy + virt-controller-proxy --> virt-controller + end + subgraph p-virt-api-deploy ["`Deploy/virt-api`"] + virt-api("`container: + virt-api`") + virt-api-proxy{{"container: + proxy"}} + virt-api --> virt-api-proxy + virt-api-proxy --> virt-api + end + + subgraph p-virt-handler-deploy ["`DaemonSet/virt-handler`"] + virt-handler("`container: + virt-handler`") + virt-handler-proxy{{"container: + proxy"}} + virt-handler --> virt-handler-proxy + virt-handler-proxy --> virt-handler + end + end + + subgraph kubeapi ["control-plane"] + kube-api["`Kubernetes API Server`"] + end + + virt-operator-proxy <----> kube-api + virt-controller-proxy <----> kube-api + virt-api-proxy <----> kube-api + virt-handler-proxy <----> kube-api + + subgraph cdi ["CDI"] + subgraph cdi-operator-deploy ["`Deploy/cdi-operator`"] + cdi-operator-proxy{{"container: + proxy"}} + cdi-operator("`container: + virt-handler`") + cdi-operator --> cdi-operator-proxy + cdi-operator-proxy --> cdi-operator + end + + subgraph cdi-deployment-deploy ["`Deploy/cdi-deployment`"] + cdi-deployment-proxy{{"container: + proxy"}} + cdi-deployment("`container: + cdi-eployment`") + cdi-deployment --> cdi-deployment-proxy + cdi-deployment-proxy --> cdi-deployment + end + + subgraph cdi-api-deploy ["`Deploy/cdi-api`"] + cdi-api-proxy{{"container: + proxy"}} + cdi-api("`container: + cdi-api`") + cdi-api --> cdi-api-proxy + cdi-api-proxy --> cdi-api + end + + subgraph cdi-exportproxy-deploy ["`Deploy/cdi-exportproxy`"] + cdi-exportproxy-proxy{{"container: + proxy"}} + cdi-exportproxy("`container: + cdi-exportproxy`") + cdi-exportproxy --> cdi-exportproxy-proxy + cdi-exportproxy-proxy --> cdi-exportproxy + end + end + kube-api <----> cdi-operator-proxy + kube-api <----> cdi-deployment-proxy + kube-api <----> cdi-api-proxy + kube-api <----> cdi-exportproxy-proxy + + + subgraph d8virt ["D8 API"] + subgraph d8-virt-deploy ["Deploy/virtualization-controller"] + d8-virt-controller-proxy("`container: + proxy`") + d8-virt-controller("`container: + virtualization-controller`") + d8-virt-controller --> d8-virt-controller-proxy + d8-virt-controller-proxy --> d8-virt-controller + end + end + + kube-api <----> d8-virt-controller-proxy +``` + +Variation (block diagram seems not so powerful as flowchart) +```mermaid +block-beta + columns 5 + + %% Main containers in kubevirt Pods + virtoperator["virt-operator"] + virtapi["virt-api"] + virtcontroller["virt-controller"] + virthandler["virt-handler"] + virtexportproxy["virt-exportproxy"] + + %% Space for links. + space:5 + %% Links between containers. + virtoperator --> virtoperatorproxy + %%virtoperatorproxy --> virtoperator + virtapi --> virtapiproxy + virtcontroller --> virtcontrollerproxy + virthandler --> virthandlerproxy + virtexportproxy --> virtexportproxyproxy + + %% Proxies in kubevirt Pods. + virtoperatorproxy(["proxy"]) + virtapiproxy(["proxy"]) + virtcontrollerproxy(["proxy"]) + virthandlerproxy(["proxy"]) + virtexportproxyproxy(["proxy"]) + + space:5 + + space + kubeapiserver{{"Kubernetes API Server"}}:3 + space + + virtoperatorproxy --> kubeapiserver + %%kubeapiserver --> virtoperatorproxy + virtapiproxy --> kubeapiserver + virtcontrollerproxy --> kubeapiserver + virthandlerproxy --> kubeapiserver + virtexportproxyproxy --> kubeapiserver + + space:5 + cdioperatorproxy --> kubeapiserver + cdiapiproxy --> kubeapiserver + cdideploymentproxy --> kubeapiserver + cdiuploadproxyproxy --> kubeapiserver + virtualizationcontrollerproxy --> kubeapiserver + + %% Proxies in CDI Pods. + cdioperatorproxy(["proxy"]) + cdiapiproxy(["proxy"]) + cdideploymentproxy(["proxy"]) + cdiuploadproxyproxy(["proxy"]) + virtualizationcontrollerproxy(["proxy"]) + + %% Links inside CDI Pods. + space:5 + cdioperator --> cdioperatorproxy + cdiapi--> cdiapiproxy + cdideployment --> cdideploymentproxy + cdiuploadproxy --> cdiuploadproxyproxy + virtualizationcontroller --> virtualizationcontrollerproxy + + cdioperator["cdi-operator"] + cdiapi["cdi-api"] + cdideployment["cdi-deployment"] + cdiuploadproxy["cdi-uploadproxy"] + virtualizationcontroller["virtualization- + controller"] +``` + +### Changes to add proxy to the Pod +- Add a ConfigMap with a simple kubeconfig points to the local proxy. + ``` + ... + clusters: + - cluster: + server: http://127.0.0.1:23915 + ... + ``` +- Add a volume and a volumeMount to pass new kubeconfig as file to the main container. +- Set KUBECONFIG variable in the main container. File should contain configuration to connect to proxy port. + - Note: kubevirt containers use --kubeconfig flag, cdi containers use KUBECONFIG env variable. +- Add a new sidecar container with the proxy. + - Set WEBHOOK_ADDRESS if webhook proxying is required. + - Add volumeMount with a certificate and set WEBHOOK_CERT_FILE and WEBHOOK_KEY_FILE to use the certificate. + - Add port 24192 to the webhook Service to use the certificate without issuing new one with changed ServerName. + +## API client proxying + +Implemented rewrites: +- apiGroup, kind, metadata.ownerReferences for Kubevirt and CDI Custom Resources. +- metadata.ownerReferences for Pod +- rules for Role, ClusterRole +- webhooks[].rules for ValidatingWebhookConfiguration, MutatingWebhookConfiguration +- metadata.name, spec.group, spec.names for CustomResourceDefinition. +- patch /spec for CustomResourceDefinition. +- fieldSelector=metadata.name=&watch=true for CRD. +- request.resource, request.object, request.kind, etc. for AdmissionReview. + +TODO: +- labels and annotations for Kubevirt and CDI CRs and all kubevirt related resources, Nodes and Pods. +- patches in general. +- SubjectAccessReview https://dev-k8sref-io.web.app/docs/authorization/subjectaccessreview-v1/ + +```plantuml +@startuml +box "Pod with Controller" #fff +participant "container\nname: controller" as ctrl +note over ctrl +Use KUBECONFIG file to connect +to local proxy instead of +directly using API server: +""clusters:"" +""- cluster:"" +"" server: http://127.0.0.1:23915"" +endnote +queue "additional container\nname: proxy" as proxy +/ note over proxy +Listen on ""127.0.0.1:23915"" +and pass requests to +Kubernetes API Server +endnote +endbox +box "Control Plane" #fff +participant "Kubernetes\nAPI Server" as kube_api +endbox + +== Get, List, Delete operations == + +ctrl -> proxy : Request operation via endpoint:\n\n/apis/kubevirt.io/v1/virtualmachines +proxy -> kube_api : Rewrite endpoint, pass request to:\n\n/apis/x.virtualization.deckhouse.io↩︎\n/v1/prefixedvirtualmachines + +kube_api -> proxy : Response with renamed resources:\n\napiVersion: x.virtualization.deckhouse.io/v1\nkind: PrefixedVirtualMachine +proxy -> ctrl : Rewrite payload, pass\nresponse with restored resources:\n\napiVersion: kubevirt.io/v1\nkind: VirtualMachine + +== Create, Update, Patch operations == + +ctrl -> proxy : Request operation via endpoint:\n\n/apis/kubevirt.io/v1/virtualmachines\n\nA payload contains original resources:\n\napiVersion: kubevirt.io/v1\nkind: VirtualMachine +proxy -> kube_api : Rewrite endpoint and payload,\npass request with renamed resources:\n\n/apis/x.virtualization.deckhouse.io↩︎\n/v1/prefixedvirtualmachines\n\napiVersion: x.virtualization.deckhouse.io/v1\nkind: PrefixedVirtualMachine + +kube_api -> proxy : Response with renamed resources:\n\napiVersion: x.virtualization.deckhouse.io/v1\nkind: PrefixedVirtualMachine +proxy -> ctrl : Rewrite payload, pass\nresponse with restored resources:\n\napiVersion: kubevirt.io/v1\nkind: VirtualMachine + +== Watch operation == + +ctrl -> proxy : Request WATCH operation via endpoint:\n\n/apis/kubevirt.io↩︎\n/v1/virtualmachines?watch=true +activate proxy +proxy -> kube_api : Rewrite endpoint, pass request to:\n\n/apis/x.virtualization.deckhouse.io↩︎\n/v1/prefixedvirtualmachines?watch=true +activate kube_api + +kube_api -> kube_api : Generate\nWATCH\nevents + +kube_api -> proxy : ADDED, MODIFIED or DELETED\nevent with renamed resource:\n\napiVersion: x.virtualization.deckhouse.io/v1\nkind: PrefixedVirtualMachine +activate proxy +proxy -> ctrl : Rewrite payload, pass\nevent with restored resource:\n\napiVersion: kubevirt.io/v1\nkind: VirtualMachine +deactivate proxy + +kube_api -> proxy : BOOKMARK event with renamed resource:\n\napiVersion: x.virtualization.deckhouse.io/v1\nkind: PrefixedVirtualMachine +activate proxy +proxy -> ctrl : Rewrite payload, pass\nevent with restored resource:\n\napiVersion: kubevirt.io/v1\nkind: VirtualMachine +deactivate proxy + +kube_api -> proxy : Stop WATCH operation +deactivate kube_api +proxy -> ctrl : Stop WATCH operation +deactivate proxy + +@endplantuml +``` + + +## Webhook proxying + +Kubernetes API Server connects to proxy, so proxy will pass AdmissionReview to real webhook. Proxy may rewrite JSON payloads +for different purposes, e.g. resources renaming. + +Additional changes: + +- A targetPort in the webhook Service should point to proxy container. +- A proxy container should mount secret with certificates. + +```plantuml +@startuml +box "Pod with Controller" #fff +participant "container\nname: controller" as ctrl +queue "additional container\nname: proxy" as proxy +endbox +box "Control Plane" #fff +participant "Kubernetes\nAPI Server" as kube_api +endbox + +note over ctrl +Listen on ""0.0.0.0:9443"" +endnote +/ note over proxy +Listen on ""0.0.0.0:24192"" +and pass requests to +the controller ""127.0.0.1:9443"" +endnote +/ note over kube_api +Pass AdmissionReview to Pod +endnote + +== Webhook handling == + +kube_api -> proxy : Request admission review via\nconfigured endpoint:\n\n/validate-x-virtualization-↩︎\ndeckhouse-io-prefixed-virtualmachines\n\nA payload contains renamed resource:\n\napiVersion: x.virtualization.deckhouse.io/v1\nkind: PrefixedVirtualMachine +proxy -> ctrl : Rewrite admission review, pass\nrequest with restored resource:\n\napiVersion: kubevirt.io/v1\nkind: VirtualMachine + +... Validating webhook response ... +ctrl -> proxy : AdmissionReview response +proxy -> kube_api : No rewrite, pass as-is. + +... Mutating webhook response ... +ctrl -> proxy : AdmissionReview response\nwith the patch +proxy -> kube_api : Rewrite ownerRef patch if\nresponse.patchType == JSONPatch\nand patch operates on the ownerRef content + + +@enduml +``` + +```mermaid +--- +config: + htmlLabels: false +--- + +sequenceDiagram + + box Pod with controller + participant ctrl as container
name: controller + participant proxy as container
name: proxy + end + + Note over ctrl: Listen on 0.0.0.0:9443 + Note over proxy: Listen on 0.0.0.0:24192
and pass requests to
127.0.0.1:9443 + + box Control plane + participant kubeapi as Kubernetes
API Server + end + note over kubeapi: Request webhook with AdmissionReview + + kubeapi --> ctrl: Webhook handling + + kubeapi ->>+ proxy: Send AdmissionReview with
renamed resources
apiVersion: x.virtualization.deckhouse.io
PrefixedVirtualMachine + + proxy ->>+ ctrl: Proxy restores resource:
apiGroup, kind, ownerReferences
apiVersion: kubevirt.io
kind: VirtualMachine + + ctrl ->>- proxy: AdmissionReview
with webhook response + + alt Validating webhook response + proxy ->> kubeapi: No rewrite, pass as-is + else Mutating webhook response + proxy ->>- kubeapi: Rewrite patch if
ownerReferences is modified + end + + + + %%participant Bob + %% ctrl->>John: "`This **is** _Markdown_`" + %%loop HealthCheck + %% John->>John: Fight against hypochondria + %%end + %%Note right of John: Rational thoughts
prevail! + %%John-->>ctrl: Great! + %%John->>Bob: How about you? + %%Bob-->>John: Jolly good! +``` diff --git a/images/kube-api-proxy/Taskfile.dist.yaml b/images/kube-api-proxy/Taskfile.dist.yaml new file mode 100644 index 000000000..eca31a942 --- /dev/null +++ b/images/kube-api-proxy/Taskfile.dist.yaml @@ -0,0 +1,82 @@ +version: "3" + +silent: true + +includes: + my: + taskfile: Taskfile.my.yaml + optional: true + +vars: + DevRegistry: "dev-registry.deckhouse.io/virt/dev/$USER" + +tasks: + dev:build: + desc: "build latest image with proxy and test-controller" + cmds: + - | + docker build . -t {{.DevRegistry}}/kube-api-proxy:latest -f local/Dockerfile + docker push {{.DevRegistry}}/kube-api-proxy:latest + + dev:deploy: + desc: "apply manifest with proxy and test-controller" + cmds: + - | + if ! kubectl get no 2>&1 >/dev/null ; then + echo Restart cluster connection + exit 1 + fi + - | + kubectl -n kproxy apply -f local/proxy.yaml + + dev:restart: + desc: "restart deployment" + cmds: + - | + if ! kubectl get no 2>&1 >/dev/null ; then + echo Restart cluster connection + exit 1 + fi + - | + kubectl -n kproxy scale deployment/kube-api-proxy --replicas=0 + kubectl -n kproxy scale deployment/kube-api-proxy --replicas=1 + + dev:redeploy: + desc: "build, deploy, restart" + cmds: + - | + if ! kubectl get no 2>&1 >/dev/null ; then + echo Restart cluster connection + exit 1 + fi + - task: dev:build + - task: dev:deploy + - task: dev:restart + - | + sleep 3 + kubectl -n kproxy get all + + dev:curl: + desc: "run curl in proxy deployment" + cmds: + - | + kubectl -n kproxy exec -t deploy/kube-api-proxy -- curl {{.CLI_ARGS}} + + dev:kubectl: + desc: "run kubectl in proxy deployment" + cmds: + - | + kubectl -n kproxy exec -ti deploy/kube-api-proxy -- kubectl -s 127.0.0.1:23916 {{.CLI_ARGS}} + #kubectl -n d8-virtualization exec -ti deploy/virt-operator -- kubectl -s 127.0.0.1:23915 {{.CLI_ARGS}} + + logs:proxy: + desc: "Show proxy logs" + cmds: + - | + kubectl -n kproxy logs deployments/kube-api-proxy -c proxy-only -f + + logs:controller: + desc: "Show test-controller logs" + cmds: + - | + kubectl -n kproxy logs deployments/kube-api-proxy -c controller -f diff --git a/images/kube-api-proxy/cmd/kube-api-proxy/main.go b/images/kube-api-proxy/cmd/kube-api-proxy/main.go new file mode 100644 index 000000000..c37fda258 --- /dev/null +++ b/images/kube-api-proxy/cmd/kube-api-proxy/main.go @@ -0,0 +1,140 @@ +package main + +import ( + "kube-api-proxy/pkg/kubevirt" + logutil "kube-api-proxy/pkg/log" + "kube-api-proxy/pkg/proxy" + "kube-api-proxy/pkg/rewriter" + "kube-api-proxy/pkg/server" + "kube-api-proxy/pkg/target" + log "log/slog" + "os" +) + +// This proxy is a proof-of-concept of proxying Kubernetes API requests +// with rewrites. +// +// It assumes presence of KUBERNETES_* environment variables and files +// in /var/run/secrets/kubernetes.io/serviceaccount (token and ca.crt). +// +// A client behind the proxy should connect to 127.0.0.1:$PROXY_PORT +// using plain http. Example of kubeconfig file: +// apiVersion: v1 +// kind: Config +// clusters: +// - cluster: +// server: http://127.0.0.1:23915 +// name: proxy.api.server +// contexts: +// - context: +// cluster: proxy.api.server +// name: proxy.api.server +// current-context: proxy.api.server + +const ( + loopbackAddr = "127.0.0.1" + anyAddr = "0.0.0.0" + defaultAPIClientProxyPort = "23915" + defaultWebhookProxyPort = "24192" +) + +func main() { + log.Info("Start proxy 20240404.01") + + // Load rules from file or use default kubevirt rules. + rewriteRules := kubevirt.KubevirtRewriteRules + if os.Getenv("RULES_PATH") != "" { + rulesFromFile, err := rewriter.LoadRules(os.Getenv("RULES_PATH")) + if err != nil { + log.Error("Load rules from %s: %v", os.Getenv("RULES_PATH"), err) + os.Exit(1) + } + rewriteRules = rulesFromFile + } + + proxies := make([]*server.HTTPServer, 0) + + // Register direct proxy from local Kubernetes API client to Kubernetes API server. + if os.Getenv("CLIENT_PROXY") == "no" { + log.Info("Will not start client proxy: CLIENT_PROXY=no") + } else { + config, err := target.NewKubernetesTarget() + if err != nil { + log.Error("Load Kubernetes REST", logutil.SlogErr(err)) + os.Exit(1) + } + lAddr := server.ConstructListenAddr( + os.Getenv("CLIENT_PROXY_ADDRESS"), os.Getenv("CLIENT_PROXY_PORT"), + loopbackAddr, defaultAPIClientProxyPort) + rwr := &rewriter.RuleBasedRewriter{ + Rules: rewriteRules, + } + proxyHandler := &proxy.Handler{ + Name: "kube-api", + TargetClient: config.Client, + TargetURL: config.APIServerURL, + ProxyMode: proxy.ToRenamed, + Rewriter: rwr, + } + proxySrv := &server.HTTPServer{ + InstanceDesc: "API Client proxy", + ListenAddr: lAddr, + RootHandler: proxyHandler, + } + proxies = append(proxies, proxySrv) + } + + // Register reverse proxy from Kubernetes API server to local webhook server. + if os.Getenv("WEBHOOK_ADDRESS") == "" { + log.Info("Will not start webhook proxy for empty WEBHOOK_ADDRESS") + } else { + config, err := target.NewWebhookTarget() + if err != nil { + log.Error("Configure webhook client", logutil.SlogErr(err)) + os.Exit(1) + } + lAddr := server.ConstructListenAddr( + os.Getenv("WEBHOOK_PROXY_ADDRESS"), os.Getenv("WEBHOOK_PROXY_PORT"), + anyAddr, defaultWebhookProxyPort) + rwr := &rewriter.RuleBasedRewriter{ + Rules: rewriteRules, + } + proxyHandler := &proxy.Handler{ + Name: "webhook", + TargetClient: config.Client, + TargetURL: config.URL, + ProxyMode: proxy.ToOriginal, + Rewriter: rwr, + } + proxySrv := &server.HTTPServer{ + InstanceDesc: "Webhook proxy", + ListenAddr: lAddr, + RootHandler: proxyHandler, + CertManager: config.CertManager, + } + proxies = append(proxies, proxySrv) + } + + if len(proxies) == 0 { + log.Info("No proxies to start, exit") + return + } + + // Start proxies and block the main process until at least one proxy stops. + proxyGroup := server.NewRunnableGroup() + for i := range proxies { + proxyGroup.Add(proxies[i]) + } + // Block while proxies are running. + proxyGroup.Start() + + // Log errors for each instance and exit. + exitCode := 0 + for _, srv := range proxies { + if srv.Err != nil { + log.Error(srv.InstanceDesc, logutil.SlogErr(srv.Err)) + exitCode = 1 + } + } + os.Exit(exitCode) +} diff --git a/images/kube-api-proxy/go.mod b/images/kube-api-proxy/go.mod new file mode 100644 index 000000000..130933a28 --- /dev/null +++ b/images/kube-api-proxy/go.mod @@ -0,0 +1,46 @@ +module kube-api-proxy + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + github.com/tidwall/gjson v1.17.1 + github.com/tidwall/sjson v1.2.5 + k8s.io/apimachinery v0.28.0-beta.0 + k8s.io/client-go v0.28.0-beta.0 + sigs.k8s.io/controller-runtime v0.15.1-0.20230728161957-7f0c6dc440f3 + sigs.k8s.io/yaml v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/oauth2 v0.8.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.28.0-beta.0 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect +) diff --git a/images/kube-api-proxy/go.sum b/images/kube-api-proxy/go.sum new file mode 100644 index 000000000..7c02f3e47 --- /dev/null +++ b/images/kube-api-proxy/go.sum @@ -0,0 +1,169 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.28.0-beta.0 h1:RQib3xI/dxXb2TPvSVRLvAjBjOMnU7jD0GwIAbKwBqU= +k8s.io/api v0.28.0-beta.0/go.mod h1:AF3hqmc5wvnZD2G4klXcRB9jBn8XEkr+2KvFbpwbvnw= +k8s.io/apimachinery v0.28.0-beta.0 h1:n3ksD30Isi22awAww6cnQVC8JhnID1Ow4Jhi7ylEHNY= +k8s.io/apimachinery v0.28.0-beta.0/go.mod h1:xhQIsaL3hXneGluH+0pzF7kr+VYuLS/VcYJxF1xQf+g= +k8s.io/client-go v0.28.0-beta.0 h1:qOEJLbK9Keyf3VUwwKap8VvXAcqsITDrRzhaWb/0GHY= +k8s.io/client-go v0.28.0-beta.0/go.mod h1:oCV0v/fHTnc/TUMH0XJORY6kUDh2H6t5DcLv2ISSL/4= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.15.1-0.20230728161957-7f0c6dc440f3 h1:tvLrlfTOKA84WNRHf9N6AmGVQ+MBAbHlSqX2pDow6D8= +sigs.k8s.io/controller-runtime v0.15.1-0.20230728161957-7f0c6dc440f3/go.mod h1:l6pJAr9U2OCzEFeSM37u7Av5pYS5NNXDV5Mesb4Ybgg= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/images/kube-api-proxy/local/Dockerfile b/images/kube-api-proxy/local/Dockerfile new file mode 100644 index 000000000..8c7e3690e --- /dev/null +++ b/images/kube-api-proxy/local/Dockerfile @@ -0,0 +1,39 @@ +# Go builder. +FROM golang:1.21-alpine3.19 AS builder + +# Cache-friendly download of go dependencies. +ADD go.mod go.sum /app/ +WORKDIR /app +RUN go mod download + +ADD . /app + +RUN GOOS=linux \ + go build -o proxy ./cmd/kube-api-proxy + +# Go builder. +FROM golang:1.21-alpine3.19 AS builder-test-controller + +# Cache-friendly download of go dependencies. +ADD local/test-controller/go.mod local/test-controller/go.sum /app/ +WORKDIR /app +RUN go mod download + +ADD local/test-controller/main.go /app/ + +RUN GOOS=linux \ + go build -o test-controller . + +FROM alpine:3.19 +RUN apk --no-cache add ca-certificates bash sed tini curl && \ + kubectlArch=linux/amd64 && \ + echo "Download kubectl for ${kubectlArch}" && \ + wget https://storage.googleapis.com/kubernetes-release/release/v1.27.5/bin/${kubectlArch}/kubectl -O /bin/kubectl && \ + chmod +x /bin/kubectl +COPY --from=builder /app/proxy / +COPY --from=builder-test-controller /app/test-controller / +ADD local/proxy.kubeconfig / + +# Use user nobody. +USER 65534:65534 +WORKDIR / diff --git a/images/kube-api-proxy/local/proxy-gen-certs.sh b/images/kube-api-proxy/local/proxy-gen-certs.sh new file mode 100755 index 000000000..68d12bd3a --- /dev/null +++ b/images/kube-api-proxy/local/proxy-gen-certs.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +NAMESPACE=kproxy +SERVICE_NAME=test-admission-webhook +CN="api proxying tests for validating webhook" +OUTDIR=proxy-certs + +COMMON_NAME=${SERVICE_NAME}.${NAMESPACE} + +set -eo pipefail + +echo ================================================================= +echo THIS SCRIPT IS NOT SECURE! USE IT ONLY FOR DEMONSTATION PURPOSES. +echo ================================================================= +echo + +mkdir -p ${OUTDIR} && cd ${OUTDIR} + +if [[ -e ca.csr ]] ; then + read -p "Regenerate certificates? (yes/no) [no]: " + if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]] + then + exit 0 + fi +fi + +RM_FILES="ca* cert*" +echo ">>> Remove ${RM_FILES}" +rm -f $RM_FILES + +echo ">>> Generate CA key and certificate" +cat <>> Generate cert.key and cert.crt" +cat < ./../../../../api + +// TODO: delete this replaces after fixing https://github.com/golang/go/issues/66403. +replace ( + github.com/cilium/proxy => github.com/cilium/proxy v0.0.0-20231202123106-38b645b854f3 + github.com/markbates/safe => github.com/markbates/safe v1.0.1 + k8s.io/api => k8s.io/api v0.29.2 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.29.2 + k8s.io/apimachinery => k8s.io/apimachinery v0.29.2 + k8s.io/apiserver => k8s.io/apiserver v0.29.2 + k8s.io/code-generator => k8s.io/code-generator v0.29.2 + k8s.io/component-base => k8s.io/component-base v0.29.2 + k8s.io/kms => k8s.io/kms v0.29.2 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch/v5 v5.8.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 // indirect + github.com/openshift/custom-resource-status v1.1.2 // indirect + github.com/pborman/uuid v1.2.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/component-base v0.29.2 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/images/kube-api-proxy/local/test-controller/go.sum b/images/kube-api-proxy/local/test-controller/go.sum new file mode 100644 index 000000000..e0ca07bdf --- /dev/null +++ b/images/kube-api-proxy/local/test-controller/go.sum @@ -0,0 +1,484 @@ +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckhouse/virtualization/api v0.0.0-20240417135227-efb465e54575 h1:FdSicGvp9Gz1dvrzV7vVkMAlEMYUWMKq/QLKeZxZOtw= +github.com/deckhouse/virtualization/api v0.0.0-20240417135227-efb465e54575/go.mod h1:1tfoFeZmlKqq6jEuSfIpdrxsBpOcMajYaCbO94pVQLs= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= +github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= +github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= +github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= +github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= +github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= +github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= +github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 h1:t/CahSnpqY46sQR01SoS+Jt0jtjgmhgE6lFmRnO4q70= +github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= +github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= +github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= +github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= +k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= +k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg= +k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8= +k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= +k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= +k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= +k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= +k8s.io/code-generator v0.29.2/go.mod h1:FwFi3C9jCrmbPjekhaCYcYG1n07CYiW1+PAPCockaos= +k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8= +k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +kubevirt.io/api v1.0.0 h1:RBdXP5CDhE0v5qL2OUQdrYyRrHe/F68Z91GWqBDF6nw= +kubevirt.io/api v1.0.0/go.mod h1:CJ4vZsaWhVN3jNbyc9y3lIZhw8nUHbWjap0xHABQiqc= +kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= +kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= +kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= +sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= +sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/images/kube-api-proxy/local/test-controller/main.go b/images/kube-api-proxy/local/test-controller/main.go new file mode 100644 index 000000000..916880a3a --- /dev/null +++ b/images/kube-api-proxy/local/test-controller/main.go @@ -0,0 +1,353 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + "runtime" + "strconv" + + virtv1alpha2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/go-logr/logr" + "go.uber.org/zap/zapcore" + corev1 "k8s.io/api/core/v1" + extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiruntime "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" + kvv1 "kubevirt.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/manager/signals" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +var ( + log = logf.Log.WithName("cmd") + resourcesSchemeFuncs = []func(*apiruntime.Scheme) error{ + clientgoscheme.AddToScheme, + extv1.AddToScheme, + kvv1.AddToScheme, + virtv1alpha2.AddToScheme, + } +) + +const ( + podNamespaceVar = "POD_NAMESPACE" + defaultVerbosity = "1" +) + +func setupLogger() { + verbose := defaultVerbosity + if verboseEnvVarVal := os.Getenv("VERBOSITY"); verboseEnvVarVal != "" { + verbose = verboseEnvVarVal + } + // visit actual flags passed in and if passed check -v and set verbose + if fv := flag.Lookup("v"); fv != nil { + verbose = fv.Value.String() + } + if verbose == defaultVerbosity { + log.V(1).Info(fmt.Sprintf("Note: increase the -v level in the controller deployment for more detailed logging, eg. -v=%d or -v=%d\n", 2, 3)) + } + verbosityLevel, err := strconv.Atoi(verbose) + debug := false + if err == nil && verbosityLevel > 1 { + debug = true + } + + // The logger instantiated here can be changed to any logger + // implementing the logr.Logger interface. This logger will + // be propagated through the whole operator, generating + // uniform and structured logs. + logf.SetLogger(zap.New(zap.Level(zapcore.Level(-1*verbosityLevel)), zap.UseDevMode(debug))) +} + +func printVersion() { + log.Info(fmt.Sprintf("Go Version: %s", runtime.Version())) + log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)) +} + +func main() { + flag.Parse() + + setupLogger() + printVersion() + + // Get a config to talk to the apiserver + cfg, err := config.GetConfig() + if err != nil { + log.Error(err, "") + os.Exit(1) + } + + leaderElectionNS := os.Getenv(podNamespaceVar) + if leaderElectionNS == "" { + leaderElectionNS = "default" + } + + // Setup scheme for all resources + scheme := apiruntime.NewScheme() + for _, f := range resourcesSchemeFuncs { + err = f(scheme) + if err != nil { + log.Error(err, "Failed to add to scheme") + os.Exit(1) + } + } + + managerOpts := manager.Options{ + // This controller watches resources in all namespaces. + LeaderElection: false, + LeaderElectionNamespace: leaderElectionNS, + LeaderElectionID: "test-controller-leader-election-helper", + LeaderElectionResourceLock: "leases", + Scheme: scheme, + } + + // Create a new Manager to provide shared dependencies and start components + mgr, err := manager.New(cfg, managerOpts) + if err != nil { + log.Error(err, "") + os.Exit(1) + } + + log.Info("Bootstrapping the Manager.") + + // Setup context to gracefully handle termination. + ctx := signals.SetupSignalHandler() + + // Add initial lister to sync rules and routes at start. + initLister := &InitialLister{ + client: mgr.GetClient(), + log: log, + } + err = mgr.Add(initLister) + if err != nil { + log.Error(err, "add initial lister to the manager") + } + + // + if _, err := NewController(ctx, mgr, log); err != nil { + log.Error(err, "") + os.Exit(1) + } + + // Start the Manager. + if err := mgr.Start(ctx); err != nil { + log.Error(err, "manager exited non-zero") + os.Exit(1) + } +} + +// InitialLister is a Runnable implementatin to access existing objects +// before handling any event with Reconcile method. +type InitialLister struct { + log logr.Logger + client client.Client +} + +func (i *InitialLister) Start(ctx context.Context) error { + cl := i.client + + // List VMs, Pods, CRDs before starting manager. + vms := virtv1alpha2.VirtualMachineList{} + err := cl.List(ctx, &vms) + if err != nil { + i.log.Error(err, "list VMs") + return err + } + log.Info(fmt.Sprintf("List returns %d VMs", len(vms.Items))) + for _, vm := range vms.Items { + i.log.Info(fmt.Sprintf("observe VM %s/%s at start", vm.GetNamespace(), vm.GetName())) + } + + pods := corev1.PodList{} + err = cl.List(ctx, &pods, client.InNamespace("")) + if err != nil { + i.log.Error(err, "list Pods") + return err + } + log.Info(fmt.Sprintf("List returns %d Pods", len(pods.Items))) + for _, pod := range pods.Items { + i.log.Info(fmt.Sprintf("observe Pod %s/%s at start", pod.GetNamespace(), pod.GetName())) + } + + crds := extv1.CustomResourceDefinitionList{} + err = cl.List(ctx, &crds, client.InNamespace("")) + if err != nil { + i.log.Error(err, "list Pods") + return err + } + log.Info(fmt.Sprintf("List returns %d CRDs", len(crds.Items))) + for _, crd := range crds.Items { + i.log.Info(fmt.Sprintf("observe CRD %s/%s at start", crd.GetNamespace(), crd.GetName())) + } + + i.log.Info("Initial listing done, proceed to manager Start") + return nil +} + +const ( + controllerName = "test-controller" +) + +func NewController( + ctx context.Context, + mgr manager.Manager, + log logr.Logger, +) (controller.Controller, error) { + reconciler := &VMReconciler{ + Client: mgr.GetClient(), + Cache: mgr.GetCache(), + Recorder: mgr.GetEventRecorderFor(controllerName), + Scheme: mgr.GetScheme(), + Log: log, + } + + c, err := controller.New(controllerName, mgr, controller.Options{Reconciler: reconciler}) + if err != nil { + return nil, err + } + + if err = SetupWatches(ctx, mgr, c, log); err != nil { + return nil, err + } + + if err = SetupWebhooks(ctx, mgr, reconciler); err != nil { + return nil, err + } + + log.Info("Initialized controller with test watches") + return c, nil +} + +// SetupWatches subscripts controller to Pods, CRDs and DVP VMs. +func SetupWatches(ctx context.Context, mgr manager.Manager, ctr controller.Controller, log logr.Logger) error { + if err := ctr.Watch(source.Kind(mgr.GetCache(), &virtv1alpha2.VirtualMachine{}), &handler.EnqueueRequestForObject{}, + //if err := ctr.Watch(source.Kind(mgr.GetCache(), &corev1.Pod{}), &handler.EnqueueRequestForObject{}, + predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + log.Info(fmt.Sprintf("Got CREATE event for VM %s/%s gvk %v", e.Object.GetNamespace(), e.Object.GetName(), e.Object.GetObjectKind().GroupVersionKind())) + return true + }, + DeleteFunc: func(e event.DeleteEvent) bool { + log.Info(fmt.Sprintf("Got DELETE event for VM %s/%s gvk %v", e.Object.GetNamespace(), e.Object.GetName(), e.Object.GetObjectKind().GroupVersionKind())) + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + log.Info(fmt.Sprintf("Got UPDATE event for VM %s/%s gvk %v", e.ObjectNew.GetNamespace(), e.ObjectNew.GetName(), e.ObjectNew.GetObjectKind().GroupVersionKind())) + return true + }, + }, + ); err != nil { + return fmt.Errorf("error setting watch on DVP VMs: %w", err) + } + + if err := ctr.Watch(source.Kind(mgr.GetCache(), &corev1.Pod{}), &handler.EnqueueRequestForObject{}, + predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + log.Info(fmt.Sprintf("Got CREATE event for Pod %s/%s gvk %v", e.Object.GetNamespace(), e.Object.GetName(), e.Object.GetObjectKind().GroupVersionKind())) + return true + }, + DeleteFunc: func(e event.DeleteEvent) bool { + log.Info(fmt.Sprintf("Got DELETE event for Pod %s/%s gvk %v", e.Object.GetNamespace(), e.Object.GetName(), e.Object.GetObjectKind().GroupVersionKind())) + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + log.Info(fmt.Sprintf("Got UPDATE event for Pod %s/%s gvk %v", e.ObjectNew.GetNamespace(), e.ObjectNew.GetName(), e.ObjectNew.GetObjectKind().GroupVersionKind())) + return true + }, + }, + ); err != nil { + return fmt.Errorf("error setting watch on Pods: %w", err) + } + + if err := ctr.Watch(source.Kind(mgr.GetCache(), &extv1.CustomResourceDefinition{}), &handler.EnqueueRequestForObject{}, + predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + log.Info(fmt.Sprintf("Got CREATE event for CRD %s/%s gvk %v", e.Object.GetNamespace(), e.Object.GetName(), e.Object.GetObjectKind().GroupVersionKind())) + return true + }, + DeleteFunc: func(e event.DeleteEvent) bool { + log.Info(fmt.Sprintf("Got DELETE event for CRD %s/%s gvk %v", e.Object.GetNamespace(), e.Object.GetName(), e.Object.GetObjectKind().GroupVersionKind())) + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + log.Info(fmt.Sprintf("Got UPDATE event for CRD %s/%s gvk %v", e.ObjectNew.GetNamespace(), e.ObjectNew.GetName(), e.ObjectNew.GetObjectKind().GroupVersionKind())) + return true + }, + }, + ); err != nil { + return fmt.Errorf("error setting watch on CRDs: %w", err) + } + + return nil +} + +func SetupWebhooks(ctx context.Context, mgr manager.Manager, validator admission.CustomValidator) error { + return builder.WebhookManagedBy(mgr). + For(&kvv1.VirtualMachine{}). + WithValidator(validator). + Complete() +} + +type VMReconciler struct { + Client client.Client + Cache cache.Cache + Recorder record.EventRecorder + Scheme *apiruntime.Scheme + Log logr.Logger +} + +func (r *VMReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { + r.Log.Info(fmt.Sprintf("Got request for %s", req.String())) + return reconcile.Result{}, nil +} + +func (r *VMReconciler) ValidateCreate(ctx context.Context, obj apiruntime.Object) (admission.Warnings, error) { + vm, ok := obj.(*kvv1.VirtualMachine) + if !ok { + return nil, fmt.Errorf("expected a new VirtualMachine but got a %T", obj) + } + + warnings := admission.Warnings{ + fmt.Sprintf("Validate new VM %s is OK, got kind %s, apiVersion %s", vm.GetName(), vm.GetObjectKind(), vm.APIVersion), + } + return warnings, nil +} + +func (r *VMReconciler) ValidateUpdate(ctx context.Context, _, newObj apiruntime.Object) (admission.Warnings, error) { + vm, ok := newObj.(*kvv1.VirtualMachine) + if !ok { + return nil, fmt.Errorf("expected a new VirtualMachine but got a %T", newObj) + } + + warnings := admission.Warnings{ + fmt.Sprintf("Validate updated VM %s is OK, got kind %s, apiVersion %s", vm.GetName(), vm.GetObjectKind(), vm.APIVersion), + } + return warnings, nil +} + +func (v *VMReconciler) ValidateDelete(_ context.Context, obj apiruntime.Object) (admission.Warnings, error) { + vm, ok := obj.(*kvv1.VirtualMachine) + if !ok { + return nil, fmt.Errorf("expected a deleted VirtualMachine but got a %T", obj) + } + + warnings := admission.Warnings{ + fmt.Sprintf("Validate deleted VM %s is OK, got kind %s, apiVersion %s", vm.GetName(), vm.GetObjectKind(), vm.APIVersion), + } + return warnings, nil +} diff --git a/images/kube-api-proxy/pkg/kubevirt/kubevirt_rules.go b/images/kube-api-proxy/pkg/kubevirt/kubevirt_rules.go new file mode 100644 index 000000000..81d735bc5 --- /dev/null +++ b/images/kube-api-proxy/pkg/kubevirt/kubevirt_rules.go @@ -0,0 +1,551 @@ +package kubevirt + +import ( + . "kube-api-proxy/pkg/rewriter" +) + +var KubevirtRewriteRules = &RewriteRules{ + KindPrefix: "DVPInternal", // KV + ResourceTypePrefix: "dvpinternal", // kv + ShortNamePrefix: "dvp", + Categories: []string{"dvpinternal"}, + RenamedGroup: "internal.virtualization.deckhouse.io", + Rules: KubevirtAPIGroupsRules, + Webhooks: KubevirtWebhooks, +} + +// TODO create generator in golang to produce below rules from Kubevirt and CDI sources so proxy can work with future versions. + +var KubevirtAPIGroupsRules = map[string]APIGroupRule{ + "cdi.kubevirt.io": { + GroupRule: GroupRule{ + Group: "cdi.kubevirt.io", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + }, + ResourceRules: map[string]ResourceRule{ + // cdiconfigs.cdi.kubevirt.io + "cdiconfigs": { + Kind: "CDIConfig", + ListKind: "CDIConfigList", + Plural: "cdiconfigs", + Singular: "cdiconfig", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{}, + }, + // cdis.cdi.kubevirt.io + "cdis": { + Kind: "CDI", + ListKind: "CDIList", + Plural: "cdis", + Singular: "cdi", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{"cdi", "cdis"}, + }, + // dataimportcrons.cdi.kubevirt.io + "dataimportcrons": { + Kind: "DataImportCron", + ListKind: "DataImportCronList", + Plural: "dataimportcrons", + Singular: "dataimportcron", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{"all"}, + ShortNames: []string{"dic", "dics"}, + }, + // datasources.cdi.kubevirt.io + "datasources": { + Kind: "DataSource", + ListKind: "DataSourceList", + Plural: "datasources", + Singular: "datasource", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{"all"}, + ShortNames: []string{"das"}, + }, + // datavolumes.cdi.kubevirt.io + "datavolumes": { + Kind: "DataVolume", + ListKind: "DataVolumeList", + Plural: "datavolumes", + Singular: "datavolume", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{"all"}, + ShortNames: []string{"dv", "dvs"}, + }, + // objecttransfers.cdi.kubevirt.io + "objecttransfers": { + Kind: "ObjectTransfer", + ListKind: "ObjectTransferList", + Plural: "objecttransfers", + Singular: "objecttransfer", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{"ot", "ots"}, + }, + // storageprofiles.cdi.kubevirt.io + "storageprofiles": { + Kind: "StorageProfile", + ListKind: "StorageProfileList", + Plural: "storageprofiles", + Singular: "storageprofile", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{}, + }, + // volumeclonesources.cdi.kubevirt.io + "volumeclonesources": { + Kind: "VolumeCloneSource", + ListKind: "VolumeCloneSourceList", + Plural: "volumeclonesources", + Singular: "volumeclonesource", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{}, + }, + // volumeimportsources.cdi.kubevirt.io + "volumeimportsources": { + Kind: "VolumeImportSource", + ListKind: "VolumeImportSourceList", + Plural: "volumeimportsources", + Singular: "volumeimportsource", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{}, + }, + // volumeuploadsources.cdi.kubevirt.io + "volumeuploadsources": { + Kind: "VolumeUploadSource", + ListKind: "VolumeUploadSourceList", + Plural: "volumeuploadsources", + Singular: "volumeuploadsource", + Versions: []string{"v1beta1"}, + PreferredVersion: "v1beta1", + Categories: []string{}, + ShortNames: []string{}, + }, + }, + }, + "kubevirt.io": { + GroupRule: GroupRule{ + Group: "kubevirt.io", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + }, + ResourceRules: map[string]ResourceRule{ + // kubevirts.kubevirt.io + "kubevirts": { + Kind: "KubeVirt", + ListKind: "KubeVirtList", + Plural: "kubevirts", + Singular: "kubevirt", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"kv", "kvs"}, + }, + // virtualmachines.kubevirt.io + "virtualmachines": { + Kind: "VirtualMachine", + ListKind: "VirtualMachineList", + Plural: "virtualmachines", + Singular: "virtualmachine", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"vm", "vms"}, + }, + // virtualmachineinstances.kubevirt.io + "virtualmachineinstances": { + Kind: "VirtualMachineInstance", + ListKind: "VirtualMachineInstanceList", + Plural: "virtualmachineinstances", + Singular: "virtualmachineinstance", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"vmi", "vmsi"}, + }, + // virtualmachineinstancemigrations.kubevirt.io + "virtualmachineinstancemigrations": { + Kind: "VirtualMachineInstanceMigration", + ListKind: "VirtualMachineInstanceMigrationList", + Plural: "virtualmachineinstancemigrations", + Singular: "virtualmachineinstancemigration", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"vmim", "vmims"}, + }, + // virtualmachineinstancepresets.kubevirt.io + "virtualmachineinstancepresets": { + Kind: "VirtualMachineInstancePreset", + ListKind: "VirtualMachineInstancePresetList", + Plural: "virtualmachineinstancepresets", + Singular: "virtualmachineinstancepreset", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"vmipreset", "vmipresets"}, + }, + // virtualmachineinstancereplicasets.kubevirt.io + "virtualmachineinstancereplicasets": { + Kind: "VirtualMachineInstanceReplicaSet", + ListKind: "VirtualMachineInstanceReplicaSetList", + Plural: "virtualmachineinstancereplicasets", + Singular: "virtualmachineinstancereplicaset", + Versions: []string{"v1", "v1alpha3"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"vmirs", "vmirss"}, + }, + }, + }, + "clone.kubevirt.io": { + GroupRule: GroupRule{ + Group: "clone.kubevirt.io", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + }, + ResourceRules: map[string]ResourceRule{ + // virtualmachineclones.clone.kubevirt.io + "virtualmachineclones": { + Kind: "VirtualMachineClone", + ListKind: "VirtualMachineCloneList", + Plural: "virtualmachineclones", + Singular: "virtualmachineclone", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{"vmclone", "vmclones"}, + }, + }, + }, + "export.kubevirt.io": { + GroupRule: GroupRule{ + Group: "export.kubevirt.io", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + }, + ResourceRules: map[string]ResourceRule{ + // virtualmachineexports.export.kubevirt.io + "virtualmachineexports": { + Kind: "VirtualMachineExport", + ListKind: "VirtualMachineExportList", + Plural: "virtualmachineexports", + Singular: "virtualmachineexport", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{"vmexport", "vmexports"}, + }, + }, + }, + "instancetype.kubevirt.io": { + GroupRule: GroupRule{ + Group: "instancetype.kubevirt.io", + Versions: []string{"v1alpha1", "v1alpha2"}, + PreferredVersion: "v1alpha2", + }, + ResourceRules: map[string]ResourceRule{ + // virtualmachineinstancetypes.instancetype.kubevirt.io + "virtualmachineinstancetypes": { + Kind: "VirtualMachineInstancetype", + ListKind: "VirtualMachineInstancetypeList", + Plural: "virtualmachineinstancetypes", + Singular: "virtualmachineinstancetype", + Versions: []string{"v1alpha1", "v1alpha2"}, + PreferredVersion: "v1alpha2", + Categories: []string{"all"}, + ShortNames: []string{"vminstancetype", "vminstancetypes", "vmf", "vmfs"}, + }, + // virtualmachinepreferences.instancetype.kubevirt.io + "virtualmachinepreferences": { + Kind: "VirtualMachinePreference", + ListKind: "VirtualMachinePreferenceList", + Plural: "virtualmachinepreferences", + Singular: "virtualmachinepreference", + Versions: []string{"v1alpha1", "v1alpha2"}, + PreferredVersion: "v1alpha2", + Categories: []string{"all"}, + ShortNames: []string{"vmpref", "vmprefs", "vmp", "vmps"}, + }, + // virtualmachineclusterinstancetypes.instancetype.kubevirt.io + "virtualmachineclusterinstancetypes": { + Kind: "VirtualMachineClusterInstancetype", + ListKind: "VirtualMachineClusterInstancetypeList", + Plural: "virtualmachineclusterinstancetypes", + Singular: "virtualmachineclusterinstancetype", + Versions: []string{"v1alpha1", "v1alpha2"}, + PreferredVersion: "v1alpha2", + Categories: []string{}, + ShortNames: []string{"vmclusterinstancetype", "vmclusterinstancetypes", "vmcf", "vmcfs"}, + }, + // virtualmachineclusterpreferences.instancetype.kubevirt.io + "virtualmachineclusterpreferences": { + Kind: "VirtualMachineClusterPreference", + ListKind: "VirtualMachineClusterPreferenceList", + Plural: "virtualmachineclusterpreferences", + Singular: "virtualmachineclusterpreference", + Versions: []string{"v1alpha1", "v1alpha2"}, + PreferredVersion: "v1alpha2", + Categories: []string{}, + ShortNames: []string{"vmcp", "vmcps"}, + }, + }, + }, + "migrations.kubevirt.io": { + GroupRule: GroupRule{ + Group: "migrations.kubevirt.io", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + }, + ResourceRules: map[string]ResourceRule{ + // migrationpolicies.migrations.kubevirt.io + "migrationpolicies": { + Kind: "MigrationPolicy", + ListKind: "MigrationPolicyList", + Plural: "migrationpolicies", + Singular: "migrationpolicy", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{}, + }, + }, + }, + "pool.kubevirt.io": { + GroupRule: GroupRule{ + Group: "pool.kubevirt.io", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + }, + ResourceRules: map[string]ResourceRule{ + // virtualmachinepools.pool.kubevirt.io + "virtualmachinepools": { + Kind: "VirtualMachinePool", + ListKind: "VirtualMachinePoolList", + Plural: "virtualmachinepools", + Singular: "virtualmachinepool", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{"vmpool", "vmpools"}, + }, + }, + }, + "snapshot.kubevirt.io": { + GroupRule: GroupRule{ + Group: "snapshot.kubevirt.io", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + }, + ResourceRules: map[string]ResourceRule{ + // virtualmachinerestores.snapshot.kubevirt.io + "virtualmachinerestores": { + Kind: "VirtualMachineRestore", + ListKind: "VirtualMachineRestoreList", + Plural: "virtualmachinerestores", + Singular: "virtualmachinerestore", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{"vmrestore", "vmrestores"}, + }, + // virtualmachinesnapshotcontents.snapshot.kubevirt.io + "virtualmachinesnapshotcontents": { + Kind: "VirtualMachineSnapshotContent", + ListKind: "VirtualMachineSnapshotContentList", + Plural: "virtualmachinesnapshotcontents", + Singular: "virtualmachinesnapshotcontent", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{"vmsnapshotcontent", "vmsnapshotcontents"}, + }, + // virtualmachinesnapshots.snapshot.kubevirt.io + "virtualmachinesnapshots": { + Kind: "VirtualMachineSnapshot", + ListKind: "VirtualMachineSnapshotList", + Plural: "virtualmachinesnapshots", + Singular: "virtualmachinesnapshot", + Versions: []string{"v1alpha1"}, + PreferredVersion: "v1alpha1", + Categories: []string{"all"}, + ShortNames: []string{"vmsnapshot", "vmsnapshots"}, + }, + }, + }, +} + +var KubevirtWebhooks = map[string]WebhookRule{ + // CDI webhooks. + // Run this in original CDI installation: + // kubectl get validatingwebhookconfiguration,mutatingwebhookconfiguration -l cdi.kubevirt.io -o json | jq '.items[] | .webhooks[] | {"path": .clientConfig.service.path, "group": (.rules[]|.apiGroups|join(",")), "resource": (.rules[]|.resources|join(",")) } | "\""+.path +"\": {\nPath: \"" + .path + "\",\nGroup: \"" + .group + "\",\nResource: \"" + .resource + "\",\n}," ' -r + // TODO create generator in golang to extract these rules from resource definitions in the cdi-operator package. + "/datavolume-mutate": { + Path: "/datavolume-mutate", + Group: "cdi.kubevirt.io", + Resource: "datavolumes", + }, + "/dataimportcron-validate": { + Path: "/dataimportcron-validate", + Group: "cdi.kubevirt.io", + Resource: "dvpinternaldataimportcrons", + }, + "/datavolume-validate": { + Path: "/datavolume-validate", + Group: "cdi.kubevirt.io", + Resource: "datavolumes", + }, + "/cdi-validate": { + Path: "/cdi-validate", + Group: "cdi.kubevirt.io", + Resource: "cdis", + }, + "/objecttransfer-validate": { + Path: "/objecttransfer-validate", + Group: "cdi.kubevirt.io", + Resource: "objecttransfers", + }, + "/populator-validate": { + Path: "/populator-validate", + Group: "cdi.kubevirt.io", + Resource: "volumeimportsources", // Also, volumeuploadsources. This field for logging only. + }, + + // Kubevirt webhooks. + // Run this in original Kubevirt installation: + // kubectl get validatingwebhookconfiguration,mutatingwebhookconfiguration -l kubevirt.io -o json | jq '.items[] | .webhooks[] | {"path": .clientConfig.service.path, "group": (.rules[]|.apiGroups|join(",")), "resource": (.rules[]|.resources|join(",")) } | "\""+.path +"\": {\nPath: \"" + .path + "\",\nGroup: \"" + .group + "\",\nResource: \"" + .resource + "\",\n}," ' + // TODO create generator in golang to extract these rules from resource definitions in the virt-operator package. + "/virtualmachineinstances-validate-create": { + Path: "/virtualmachineinstances-validate-create", + Group: "kubevirt.io", + Resource: "virtualmachineinstances", + }, + "/virtualmachineinstances-validate-update": { + Path: "/virtualmachineinstances-validate-update", + Group: "kubevirt.io", + Resource: "virtualmachineinstances", + }, + "/virtualmachines-validate": { + Path: "/virtualmachines-validate", + Group: "kubevirt.io", + Resource: "virtualmachines", + }, + "/virtualmachinereplicaset-validate": { + Path: "/virtualmachinereplicaset-validate", + Group: "kubevirt.io", + Resource: "virtualmachineinstancereplicasets", + }, + "/virtualmachinepool-validate": { + Path: "/virtualmachinepool-validate", + Group: "pool.kubevirt.io", + Resource: "virtualmachinepools", + }, + "/vmipreset-validate": { + Path: "/vmipreset-validate", + Group: "kubevirt.io", + Resource: "virtualmachineinstancepresets", + }, + "/migration-validate-create": { + Path: "/migration-validate-create", + Group: "kubevirt.io", + Resource: "virtualmachineinstancemigrations", + }, + "/migration-validate-update": { + Path: "/migration-validate-update", + Group: "kubevirt.io", + Resource: "virtualmachineinstancemigrations", + }, + "/virtualmachinesnapshots-validate": { + Path: "/virtualmachinesnapshots-validate", + Group: "snapshot.kubevirt.io", + Resource: "virtualmachinesnapshots", + }, + "/virtualmachinerestores-validate": { + Path: "/virtualmachinerestores-validate", + Group: "snapshot.kubevirt.io", + Resource: "virtualmachinerestores", + }, + "/virtualmachineexports-validate": { + Path: "/virtualmachineexports-validate", + Group: "export.kubevirt.io", + Resource: "virtualmachineexports", + }, + "/virtualmachineinstancetypes-validate": { + Path: "/virtualmachineinstancetypes-validate", + Group: "instancetype.kubevirt.io", + Resource: "virtualmachineinstancetypes", + }, + "/virtualmachineclusterinstancetypes-validate": { + Path: "/virtualmachineclusterinstancetypes-validate", + Group: "instancetype.kubevirt.io", + Resource: "virtualmachineclusterinstancetypes", + }, + "/virtualmachinepreferences-validate": { + Path: "/virtualmachinepreferences-validate", + Group: "instancetype.kubevirt.io", + Resource: "virtualmachinepreferences", + }, + "/virtualmachineclusterpreferences-validate": { + Path: "/virtualmachineclusterpreferences-validate", + Group: "instancetype.kubevirt.io", + Resource: "virtualmachineclusterpreferences", + }, + "/status-validate": { + Path: "/status-validate", + Group: "kubevirt.io", + Resource: "virtualmachines/status,virtualmachineinstancereplicasets/status,virtualmachineinstancemigrations/status", + }, + "/migration-policy-validate-create": { + Path: "/migration-policy-validate-create", + Group: "migrations.kubevirt.io", + Resource: "migrationpolicies", + }, + "/vm-clone-validate-create": { + Path: "/vm-clone-validate-create", + Group: "clone.kubevirt.io", + Resource: "virtualmachineclones", + }, + "/kubevirt-validate-delete": { + Path: "/kubevirt-validate-delete", + Group: "kubevirt.io", + Resource: "kubevirts", + }, + "/kubevirt-validate-update": { + Path: "/kubevirt-validate-update", + Group: "kubevirt.io", + Resource: "kubevirts", + }, + "/virtualmachines-mutate": { + Path: "/virtualmachines-mutate", + Group: "kubevirt.io", + Resource: "virtualmachines", + }, + "/virtualmachineinstances-mutate": { + Path: "/virtualmachineinstances-mutate", + Group: "kubevirt.io", + Resource: "virtualmachineinstances", + }, + "/migration-mutate-create": { + Path: "/migration-mutate-create", + Group: "kubevirt.io", + Resource: "virtualmachineinstancemigrations", + }, + "/vm-clone-mutate-create": { + Path: "/vm-clone-mutate-create", + Group: "clone.kubevirt.io", + Resource: "virtualmachineclones", + }, +} diff --git a/images/kube-api-proxy/pkg/kubevirt/kubevirt_rules_test.go b/images/kube-api-proxy/pkg/kubevirt/kubevirt_rules_test.go new file mode 100644 index 000000000..2303572b2 --- /dev/null +++ b/images/kube-api-proxy/pkg/kubevirt/kubevirt_rules_test.go @@ -0,0 +1,17 @@ +package kubevirt + +import ( + "fmt" + "testing" + + "sigs.k8s.io/yaml" +) + +func TestKubevirtRulesToYAML(t *testing.T) { + b, err := yaml.Marshal(KubevirtRewriteRules) + if err != nil { + t.Fatalf("should marshal kubevirt rules without error: %v", err) + } + + fmt.Printf("%s\n", string(b)) +} diff --git a/images/kube-api-proxy/pkg/log/body.go b/images/kube-api-proxy/pkg/log/body.go new file mode 100644 index 000000000..6902c6388 --- /dev/null +++ b/images/kube-api-proxy/pkg/log/body.go @@ -0,0 +1,55 @@ +package log + +import ( + "bytes" + "fmt" + "io" +) + +type ReaderLogger struct { + wrappedReader io.ReadCloser + buf bytes.Buffer +} + +func NewReaderLogger(r io.Reader) *ReaderLogger { + rdr := &ReaderLogger{} + rdr.wrappedReader = io.NopCloser(io.TeeReader(r, &rdr.buf)) + return rdr +} + +func (r *ReaderLogger) Read(p []byte) (n int, err error) { + return r.wrappedReader.Read(p) +} + +func (r *ReaderLogger) Close() error { + return r.wrappedReader.Close() +} + +func HeadString(obj interface{}, limit int) string { + readLog, ok := obj.(*ReaderLogger) + if !ok { + return "" + } + bufLen := readLog.buf.Len() + bufStr := readLog.buf.String() + if bufLen < limit { + return bufStr + } + return bufStr[0:limit] +} + +func HeadStringEx(obj interface{}, limit int) string { + s := HeadString(obj, limit) + if s == "" { + return "" + } + return fmt.Sprintf("[%d] %s", len(s), s) +} + +func HasData(obj interface{}) bool { + readLog, ok := obj.(*ReaderLogger) + if !ok { + return false + } + return readLog.buf.Len() > 0 +} diff --git a/images/kube-api-proxy/pkg/log/error.go b/images/kube-api-proxy/pkg/log/error.go new file mode 100644 index 000000000..07938567d --- /dev/null +++ b/images/kube-api-proxy/pkg/log/error.go @@ -0,0 +1,7 @@ +package log + +import "log/slog" + +func SlogErr(err error) slog.Attr { + return slog.Any("err", err) +} diff --git a/images/kube-api-proxy/pkg/proxy/doc.go b/images/kube-api-proxy/pkg/proxy/doc.go new file mode 100644 index 000000000..301388b37 --- /dev/null +++ b/images/kube-api-proxy/pkg/proxy/doc.go @@ -0,0 +1,39 @@ +package proxy + +// Proxy handler implements 2 types of proxy: +// - proxy for client interaction with Kubernetes API Server +// - proxy to deliver AdmissionReview requests from Kubernetes API Server to webhook server +// +// Proxy for webhooks acts as follows: +// ServerHTTP method reads request from Kubernetes API Server, restores apiVersion, kind and +// ownerRefs, sends it to real webhook, renames apiVersion, kind, and ownerRefs +// and sends it back to Kubernetes API Server. +// +// +--------------------------------------------+ +// | Kubernetes API Server | +// +--------------------------------------------+ +// | ^ +// | | +// 1. AdmissionReview request 4. AdmissionReview response +// webhook.srv:443/webhook-endpoint | +// apiVersion: renamed-group.io | +// kind: PrefixedResource | +// | | +// v | +// +-----------------------------------------------------+ +// | Proxy | +// | 2. Restore 3. Rename | +// | apiVersion, kind field if Admission response | +// | in Admission request has patchType: JSONPatch | +// | in Admission request rename kind in ownerRef | +// +-----------------------------------------------------+ +// | ^ +// 127.0.0.1:9443/webhook-endpoint | +// apiVersion: original-group.io | +// kind: Resource | +// | | +// v | +// +-------------------------------------------------------+ +// | Webhook | +// | handles request ---> sends response | +// +-------------------------------------------------------+ diff --git a/images/kube-api-proxy/pkg/proxy/handler.go b/images/kube-api-proxy/pkg/proxy/handler.go new file mode 100644 index 000000000..ee2098d43 --- /dev/null +++ b/images/kube-api-proxy/pkg/proxy/handler.go @@ -0,0 +1,420 @@ +package proxy + +import ( + "bytes" + "compress/flate" + "compress/gzip" + "fmt" + "io" + "log/slog" + "net/http" + "net/url" + "strconv" + "strings" + "sync" + + logutil "kube-api-proxy/pkg/log" + "kube-api-proxy/pkg/rewriter" +) + +type ProxyMode string + +const ( + // ToOriginal mode indicates that resource should be restored when passed to target and renamed when passing back to client. + ToOriginal ProxyMode = "original" + // ToRenamed mode indicates that resource should be renamed when passed to target and restored when passing back to client. + ToRenamed ProxyMode = "renamed" +) + +func ToTargetAction(proxyMode ProxyMode) rewriter.Action { + if proxyMode == ToRenamed { + return rewriter.Rename + } + return rewriter.Restore +} + +func FromTargetAction(proxyMode ProxyMode) rewriter.Action { + if proxyMode == ToRenamed { + return rewriter.Restore + } + return rewriter.Rename +} + +type Handler struct { + Name string + // ProxyPass is a target http client to send requests to. + // An allusion to nginx proxy_pass directive. + TargetClient *http.Client + TargetURL *url.URL + ProxyMode ProxyMode + Rewriter *rewriter.RuleBasedRewriter + m sync.Mutex +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if req == nil { + slog.Error("req is nil. something wrong") + return + } + if req.URL == nil { + slog.Error(fmt.Sprintf("req.URL is nil. something wrong. method %s RequestURI '%s' Headers %+v", req.Method, req.RequestURI, req.Header)) + return + } + + // Parse request url, prepare path rewrite. + targetReq := rewriter.NewTargetRequest(h.Rewriter, req) + + resource := targetReq.ResourceForLog() + + logger := slog.With( + slog.String("request", fmt.Sprintf("%s %s", req.Method, req.URL.Path)), + slog.String("resource", resource), + slog.String("proxy.name", h.Name), + ) + + // Set target address, cleanup RequestURI. + req.RequestURI = "" + req.URL.Scheme = h.TargetURL.Scheme + req.URL.Host = h.TargetURL.Host + + // Log request path. + rwrReq := " NO" + if targetReq.ShouldRewriteRequest() { + rwrReq = "REQ" + } + rwrResp := " NO" + if targetReq.ShouldRewriteResponse() { + rwrResp = "RESP" + } + if targetReq.Path() != req.URL.Path { + logger.Info(fmt.Sprintf("%s [%s,%s] %s -> %s", req.Method, rwrReq, rwrResp, req.URL.String(), targetReq.Path())) + } else { + logger.Info(fmt.Sprintf("%s [%s,%s] %s", req.Method, rwrReq, rwrResp, req.URL.String())) + } + + // TODO(development): Mute some logging for development: election, non-rewritable resources. + isMute := false + if !targetReq.ShouldRewriteRequest() && !targetReq.ShouldRewriteResponse() { + isMute = true + } + switch resource { + case "leases": + isMute = true + case "endpoints": + isMute = true + case "clusterrolebindings": + isMute = false + case "clustervirtualmachineimages": + isMute = false + } + if isMute { + logger = slog.New(slog.NewTextHandler(io.Discard, nil)) + } + + logger.Info(fmt.Sprintf("Request: orig headers: %+v", req.Header)) + + // Modify req to send it to target. + err := h.transformRequest(targetReq, req) + //targetReq, err := p.Rewriter.RewriteToTarget(req) + if err != nil { + logger.Error(fmt.Sprintf("Error rewriting request: %s", req.URL.String()), logutil.SlogErr(err)) + http.Error(w, "can't rewrite request", http.StatusBadRequest) + return + } + + logger.Info(fmt.Sprintf("Request: target headers: %+v", req.Header)) + + // Wrap reader to log content after transferring request Body. + if req.Body != nil { + req.Body = logutil.NewReaderLogger(req.Body) + } + + resp, err := h.TargetClient.Do(req) + if err != nil { + logger.Error("Proxy pass request error", logutil.SlogErr(err)) + http.Error(w, "Proxy pass request error", http.StatusInternalServerError) + // TODO return apimachinery NewInternalError + // https://github.com/kubernetes/apimachinery/blob/master/pkg/api/errors/errors.go + return + } + defer resp.Body.Close() + + // TODO handle resp.Status 3xx, 4xx, 5xx, etc. + + // TODO delete after development: Log head of the request body. + if logutil.HasData(req.Body) { + limit := 512 + switch resource { + case "virtualmachines", + "virtualmachines/status", + "virtualmachineinstances", + "virtualmachineinstances/status", + "clustervirtualmachineimages", + "clustervirtualmachineimages/status", + "clusterrolebindings", + "customresourcedefinitions": + limit = 32000 + } + logger.Info(fmt.Sprintf("Request: Rewritten body: %s", logutil.HeadStringEx(req.Body, limit))) + } + + if !targetReq.ShouldRewriteResponse() { + // Pass response as-is without rewriting. + logger.Info(fmt.Sprintf("RESPONSE PASS: Status %s, Headers %+v", resp.Status, resp.Header)) + passResponse(w, resp, logger) + return + } + + if targetReq.IsWatch() { + logger.Info(fmt.Sprintf("RESPONSE REWRITE STREAM Status %s, Headers %+v", resp.Status, resp.Header)) + + h.transformStream(targetReq, w, resp, logger) + return + } + + // One-time rewrite is required for client or webhook requests. + logger.Info(fmt.Sprintf("RESPONSE REWRITE ONCE Status %s, Headers %+v", resp.Status, resp.Header)) + + h.transformResponse(targetReq, w, resp, logger) + return +} + +func copyHeader(dst, src http.Header) { + for header, values := range src { + // Do not override dst header with the header from the src. + if len(dst.Values(header)) > 0 { + continue + } + for _, value := range values { + dst.Add(header, value) + } + } +} + +func encodingAwareBodyReader(resp *http.Response) (io.ReadCloser, error) { + if resp == nil { + return nil, nil + } + body := resp.Body + if body == nil { + return nil, nil + } + + var reader io.ReadCloser + var err error + + encoding := resp.Header.Get("Content-Encoding") + switch encoding { + case "gzip": + reader, err = gzip.NewReader(body) + if err != nil { + return nil, fmt.Errorf("errorf making gzip reader: %v", err) + } + return io.NopCloser(reader), nil + case "deflate": + return flate.NewReader(body), nil + } + + return body, nil +} + +// transformRequest transforms request headers and rewrites request payload to use +// request as client to the target. +// TargetMode field defines either transformer should rename resources +// if request is from the client, or restore resources if it is a call +// from the API Server to the webhook. +func (h *Handler) transformRequest(targetReq *rewriter.TargetRequest, req *http.Request) error { + if req == nil || req.URL == nil { + return fmt.Errorf("request to rewrite is empty") + } + + // Rewrite incoming payload, e.g. create, put, etc. + if targetReq.ShouldRewriteRequest() && req.Body != nil { + // Read whole request body to rewrite. + bodyBytes, err := io.ReadAll(req.Body) + if err != nil { + return fmt.Errorf("read request body: %w", err) + } + + var newBody []byte + switch req.Method { + case http.MethodPatch: + newBody, err = h.Rewriter.RewritePatch(targetReq, bodyBytes) + default: + newBody, err = h.Rewriter.RewriteJSONPayload(targetReq, bodyBytes, ToTargetAction(h.ProxyMode)) + } + if err != nil { + return err + } + + // Put new Body reader to req and fix Content-Length header. + newBodyLen := len(newBody) + if newBodyLen > 0 { + // Fix content-length if needed. + req.ContentLength = int64(newBodyLen) + if req.Header.Get("Content-Length") != "" { + req.Header.Set("Content-Length", strconv.Itoa(newBodyLen)) + } + req.Body = io.NopCloser(bytes.NewBuffer(newBody)) + } + } + + if targetReq.ShouldRewriteResponse() { + // Rewriter not work with protobuf, force JSON + // in Accept header. + newAccept := make([]string, 0) + for _, hdr := range req.Header.Values("Accept") { + if strings.Contains(hdr, "application/vnd.kubernetes.protobuf") { + newAccept = append(newAccept, "application/json") + continue + } + // Quickly support kubectl with simple hack + if strings.Contains(hdr, "application/json") && strings.Contains(hdr, "as=Table") { + newAccept = append(newAccept, "application/json") + continue + } + newAccept = append(newAccept, hdr) + } + //req.Header.Set("Accept", newAccept) + + //req.Header.Del("Accept") + req.Header["Accept"] = newAccept + + // Force JSON for watches of core resources and CRDs. + if targetReq.IsWatch() && (targetReq.IsCRD() || targetReq.IsCore()) { + if len(req.Header.Values("Accept")) == 0 { + req.Header["Accept"] = []string{"application/json"} + } + } + } + + // Set new endpoint path and query. + req.URL.Path = targetReq.Path() + req.URL.RawQuery = targetReq.RawQuery() + + return nil +} + +func passResponse(w http.ResponseWriter, resp *http.Response, logger *slog.Logger) { + copyHeader(w.Header(), resp.Header) + w.WriteHeader(resp.StatusCode) + + if resp.StatusCode != http.StatusOK { + resp.Body = logutil.NewReaderLogger(resp.Body) + } + + dst := &immediateWriter{dst: w} + _, err := io.Copy(dst, resp.Body) + if err != nil { + logger.Error(fmt.Sprintf("copy response: %v", err)) + } + + if logutil.HasData(resp.Body) { + limit := 1024 + logger.Info(fmt.Sprintf("Pass through non 200 response: status %d %s", resp.StatusCode, logutil.HeadStringEx(resp.Body, limit))) + } + + return +} + +// transformResponse rewrites payloads in responses from the target. +// +// ProxyMode field defines either rewriter should restore, or rename resources. +func (h *Handler) transformResponse(targetReq *rewriter.TargetRequest, w http.ResponseWriter, resp *http.Response, logger *slog.Logger) { + // Rewrite supports only json responses for now. + // TODO detect content type from content, header in response may be inaccurate, e.g. from webhooks. + contentType := resp.Header.Get("Content-Type") + if !strings.HasPrefix(contentType, "application/json") { + logger.Warn(fmt.Sprintf("Will not transform non JSON response from target: Content-type=%s", contentType)) + passResponse(w, resp, logger) + return + } + + // Add gzip decoder if needed. + var err error + resp.Body, err = encodingAwareBodyReader(resp) + if err != nil { + logger.Error("Error decoding response body", logutil.SlogErr(err)) + http.Error(w, "can't decode response body", http.StatusInternalServerError) + return + } + + // Read response body to buffer. Wrap Body to log it later. + bodyReader := logutil.NewReaderLogger(resp.Body) + bodyBytes, err := io.ReadAll(bodyReader) + if err != nil { + logger.Error("Error reading response payload", logutil.SlogErr(err)) + http.Error(w, "Error reading response payload", http.StatusBadGateway) + return + } + + { + limit := 1024 + logger.Info(fmt.Sprintf("Response: original body: [%d] %s", len(bodyBytes), logutil.HeadStringEx(bodyReader, limit))) + } + + //return tr.Rewriter.RewriteJSONPayload(tr.TargetReq, bodyBytes, FromTargetAction(tr.ProxyMode)) + //bodyBytes, err := h.Rewriter.RewriteFromTarget(targetReq, resp, logger) + bodyBytes, err = h.Rewriter.RewriteJSONPayload(targetReq, bodyBytes, FromTargetAction(h.ProxyMode)) + if err != nil { + logger.Error("Error rewriting response", logutil.SlogErr(err)) + http.Error(w, "can't rewrite response", http.StatusInternalServerError) + return + } + + { + limit := 1024 + if len(bodyBytes) < limit { + limit = len(bodyBytes) + } + logger.Info(fmt.Sprintf("Response: rewritten bytes: [%d] %s", len(bodyBytes), string(bodyBytes[:limit]))) + } + + copyHeader(w.Header(), resp.Header) + // Fix Content headers. + // bodyBytes are always decoded from gzip. Delete header to not break our client. + w.Header().Del("Content-Encoding") + if bodyBytes != nil { + w.Header().Set("Content-Length", strconv.Itoa(len(bodyBytes))) + } + w.WriteHeader(resp.StatusCode) + + if bodyBytes != nil { + resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + _, err := io.Copy(w, resp.Body) + if err != nil { + logger.Error(fmt.Sprintf("error writing response from target: %v", err)) + } + } + + return +} + +func (h *Handler) transformStream(targetReq *rewriter.TargetRequest, w http.ResponseWriter, resp *http.Response, logger *slog.Logger) { + copyHeader(w.Header(), resp.Header) + w.WriteHeader(resp.StatusCode) + + // Start stream handler and lock ServeHTTP while proxying watch events stream. + wsr, err := NewStreamHandler(resp.Body, w, resp.Header.Get("Content-Type"), h.Rewriter, targetReq, logger) + if err != nil { + logger.Error("Error watching stream", logutil.SlogErr(err)) + http.Error(w, fmt.Sprintf("watch stream: %v", err), http.StatusInternalServerError) + return + } + <-wsr.DoneChan() + return +} + +type immediateWriter struct { + dst io.Writer +} + +func (iw *immediateWriter) Write(p []byte) (n int, err error) { + n, err = iw.dst.Write(p) + + if flusher, ok := iw.dst.(http.Flusher); ok { + flusher.Flush() + } + + return +} diff --git a/images/kube-api-proxy/pkg/proxy/stream_handler.go b/images/kube-api-proxy/pkg/proxy/stream_handler.go new file mode 100644 index 000000000..ec95dbf15 --- /dev/null +++ b/images/kube-api-proxy/pkg/proxy/stream_handler.go @@ -0,0 +1,219 @@ +package proxy + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + log "log/slog" + "mime" + "net/http" + + "github.com/tidwall/gjson" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer/streaming" + apiutilnet "k8s.io/apimachinery/pkg/util/net" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes/scheme" + + logutil "kube-api-proxy/pkg/log" + "kube-api-proxy/pkg/rewriter" +) + +// StreamHandler reads a stream from the target, transforms events +// and sends them to the client. +type StreamHandler struct { + r io.ReadCloser + w io.Writer + rewriter *rewriter.RuleBasedRewriter + targetReq *rewriter.TargetRequest + decoder streaming.Decoder + done chan struct{} + log *log.Logger +} + +// NewStreamHandler starts a go routine to pass rewritten Watch Events +// from server to client. +// Sources: +// k8s.io/apimachinery@v0.26.1/pkg/watch/streamwatcher.go:100 receive method +// k8s.io/kubernetes@v1.13.0/staging/src/k8s.io/client-go/rest/request.go:537 wrapperFn, create framer. +// k8s.io/kubernetes@v1.13.0/staging/src/k8s.io/client-go/rest/request.go:598 instantiate watch NewDecoder +func NewStreamHandler(r io.ReadCloser, w io.Writer, contentType string, rewriter *rewriter.RuleBasedRewriter, targetReq *rewriter.TargetRequest, logger *log.Logger) (*StreamHandler, error) { + reader := logutil.NewReaderLogger(r) + wsr := &StreamHandler{ + r: reader, + w: w, + rewriter: rewriter, + targetReq: targetReq, + done: make(chan struct{}), + log: logger, + } + decoder, err := wsr.createWatchDecoder(contentType) + if err != nil { + return nil, err + } + wsr.decoder = decoder + + // Start stream proxying. + go wsr.proxy() + return wsr, nil +} + +// proxy reads result from the decoder in a loop, rewrites and writes to a client. +// Sources +// k8s.io/apimachinery@v0.26.1/pkg/watch/streamwatcher.go:100 receive method +func (s *StreamHandler) proxy() { + defer utilruntime.HandleCrash() + defer s.Stop() + for { + // Read event from the server. + var got metav1.WatchEvent + s.log.Info("Start decode from stream") + res, _, err := s.decoder.Decode(nil, &got) + s.log.Info("Got decoded WatchEvent from stream") + if err != nil { + switch err { + case io.EOF: + // watch closed normally + s.log.Info("Catch EOF from target, stop proxying the stream") + case io.ErrUnexpectedEOF: + s.log.Error("Unexpected EOF during watch stream event decoding", logutil.SlogErr(err)) + default: + if apiutilnet.IsProbableEOF(err) || apiutilnet.IsTimeout(err) { + s.log.Error("Unable to decode an event from the watch stream", logutil.SlogErr(err)) + } else { + s.log.Error("Unable to decode an event from the watch stream", logutil.SlogErr(err)) + //select { + //case <-sw.done: + //case sw.result <- Event{ + // Type: Error, + // Object: sw.reporter.AsObject(fmt.Errorf("unable to decode an event from the watch stream: %v", err)), + //}: + //} + } + } + //s.log.Info("captured bytes from the stream", logutil.HeadStringEx(s.r, 65536)) + return + } + + if res != &got { + s.log.Error("unable to decode to metav1.Event") + continue + } + + switch got.Type { + case string(watch.Added), string(watch.Modified), string(watch.Deleted), string(watch.Error), string(watch.Bookmark): + default: + s.log.Error(fmt.Sprintf("got invalid watch event type: %v", got.Type)) + continue + } + + { + group := gjson.GetBytes(got.Object.Raw, "apiVersion").String() + kind := gjson.GetBytes(got.Object.Raw, "kind").String() + name := gjson.GetBytes(got.Object.Raw, "metadata.name").String() + ns := gjson.GetBytes(got.Object.Raw, "metadata.namespace").String() + s.log.Info(fmt.Sprintf("Receive '%s' watch event with %s/%s %s/%s object", got.Type, group, kind, ns, name)) + } + + // TODO add pass-as-is for non rewritable objects. + + // Restore object. Watch responses are always from the Kubernetes API server, no need to rename. + objBytes, err := s.rewriter.RewriteJSONPayload(s.targetReq, got.Object.Raw, rewriter.Restore) + //var objBytes []byte + //switch { + //case s.targetReq.IsCore(): + // s.log.Info(fmt.Sprintf("Watch REWRITE CORE event '%s'", got.Type)) + // objBytes, err = rewriter.RewriteOwnerReferences(s.rewriter.Rules, got.Object.Raw, rewriter.Restore) + //case s.targetReq.IsCRD(): + // s.log.Info(fmt.Sprintf("Watch REWRITE CRD event '%s'", got.Type)) + // objBytes, err = rewriter.RewriteCRDOrList(s.rewriter.Rules, got.Object.Raw, rewriter.Restore, s.targetReq.OrigGroup()) + //case s.targetReq.OrigResourceType() != "": + // s.log.Info(fmt.Sprintf("Watch REWRITE event '%s'", got.Type)) + // objBytes, err = rewriter.RestoreResource(s.rewriter.Rules, got.Object.Raw, s.targetReq.OrigGroup()) + //default: + // objBytes = got.Object.Raw + //} + if err != nil { + s.log.Error(fmt.Sprintf("rewrite event '%s'", got.Type), logutil.SlogErr(err)) + continue + } + + // Write event to the client. + ev := metav1.WatchEvent{ + Type: got.Type, + Object: runtime.RawExtension{ + Raw: objBytes, + }, + } + evBytes, err := json.Marshal(ev) + if err != nil { + s.log.Error("encode restored event to bytes", logutil.SlogErr(err)) + continue + } + l := len(evBytes) + if l > 1300 { + l = 1300 + } + s.log.Info(fmt.Sprintf("restored event: %s", string(evBytes)[0:l])) + + _, err = io.Copy(s.w, io.NopCloser(bytes.NewBuffer(evBytes))) + if err != nil { + s.log.Error("write event", logutil.SlogErr(err)) + } + // Flush to send buffered content to the client. + if wr, ok := s.w.(http.Flusher); ok { + wr.Flush() + } + + // Check if application is stopped. + select { + case <-s.done: + return + default: + } + } +} + +func (s *StreamHandler) Stop() { + select { + case <-s.done: + default: + close(s.done) + } +} + +func (s *StreamHandler) DoneChan() chan struct{} { + return s.done +} + +// createSerializers +// Source +// k8s.io/client-go@v0.26.1/rest/request.go:765 newStreamWatcher +// k8s.io/apimachinery@v0.26.1/pkg/runtime/negotiate.go:70 StreamDecoder +func (s *StreamHandler) createWatchDecoder(contentType string) (streaming.Decoder, error) { + mediaType, _, err := mime.ParseMediaType(contentType) + if err != nil { + s.log.Info("Unexpected media type from the server: %q: %v", contentType, err) + } + + negotiatedSerializer := scheme.Codecs.WithoutConversion() + mediaTypes := negotiatedSerializer.SupportedMediaTypes() + info, ok := runtime.SerializerInfoForMediaType(mediaTypes, mediaType) + if !ok { + if len(contentType) != 0 || len(mediaTypes) == 0 { + return nil, fmt.Errorf("no matching serializer for media type '%s'", contentType) + } + info = mediaTypes[0] + } + if info.StreamSerializer == nil { + return nil, fmt.Errorf("no serializer for content type %s", contentType) + } + + // A chain of the framer and the serializer will split body stream into JSON objects. + frameReader := info.StreamSerializer.Framer.NewFrameReader(s.r) + streamingDecoder := streaming.NewDecoder(frameReader, info.StreamSerializer.Serializer) + return streamingDecoder, nil +} diff --git a/images/kube-api-proxy/pkg/rewriter/admission_configuration.go b/images/kube-api-proxy/pkg/rewriter/admission_configuration.go new file mode 100644 index 000000000..881ae2837 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/admission_configuration.go @@ -0,0 +1,46 @@ +package rewriter + +const ( + ValidatingWebhookConfigurationKind = "ValidatingWebhookConfiguration" + ValidatingWebhookConfigurationListKind = "ValidatingWebhookConfigurationList" + MutatingWebhookConfigurationKind = "MutatingWebhookConfiguration" + MutatingWebhookConfigurationListKind = "MutatingWebhookConfigurationList" +) + +func RewriteValidatingOrList(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + if action == Rename { + return RewriteResourceOrList(obj, ValidatingWebhookConfigurationListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "webhooks", func(webhook []byte) ([]byte, error) { + return RewriteArray(webhook, "rules", func(item []byte) ([]byte, error) { + return renameRoleRule(rules, item) + }) + }) + }) + } + return RewriteResourceOrList(obj, ValidatingWebhookConfigurationListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "webhooks", func(webhook []byte) ([]byte, error) { + return RewriteArray(webhook, "rules", func(item []byte) ([]byte, error) { + return restoreRoleRule(rules, item) + }) + }) + }) +} + +func RewriteMutatingOrList(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + if action == Rename { + return RewriteResourceOrList(obj, MutatingWebhookConfigurationListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "webhooks", func(webhook []byte) ([]byte, error) { + return RewriteArray(webhook, "rules", func(item []byte) ([]byte, error) { + return renameRoleRule(rules, item) + }) + }) + }) + } + return RewriteResourceOrList(obj, MutatingWebhookConfigurationListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "webhooks", func(webhook []byte) ([]byte, error) { + return RewriteArray(webhook, "rules", func(item []byte) ([]byte, error) { + return restoreRoleRule(rules, item) + }) + }) + }) +} diff --git a/images/kube-api-proxy/pkg/rewriter/admission_configuration_test.go b/images/kube-api-proxy/pkg/rewriter/admission_configuration_test.go new file mode 100644 index 000000000..311627663 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/admission_configuration_test.go @@ -0,0 +1,69 @@ +package rewriter + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValidatingRename(t *testing.T) { + tests := []struct { + name string + manifest string + expect string + }{ + { + "mixed resources", + `{"webhooks":[{"rules":[{"apiGroups":[""],"resources":["pods"]},{"apiGroups": ["original.group.io"], "resources": ["someresources"]}]}]}`, + `{"webhooks":[{"rules":[{"apiGroups":[""],"resources":["pods"]},{"apiGroups": ["prefixed.resources.group.io"], "resources": ["prefixedsomeresources"]}]}]}`, + }, + { + "empty object", + `{}`, + `{}`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rwr := createTestRewriter() + + resBytes, err := RewriteValidatingOrList(rwr.Rules, []byte(tt.manifest), Rename) + require.NoError(t, err, "should rename validating webhook configuration") + + actual := string(resBytes) + require.Equal(t, tt.expect, actual) + }) + } +} + +func TestValidatingRestore(t *testing.T) { + tests := []struct { + name string + manifest string + expect string + }{ + { + "mixed resources", + `{"webhooks":[{"rules":[{"apiGroups":[""],"resources":["pods"]},{"apiGroups": ["prefixed.resources.group.io"], "resources": ["prefixedsomeresources"]}]}]}`, + `{"webhooks":[{"rules":[{"apiGroups":[""],"resources":["pods"]},{"apiGroups": ["original.group.io"], "resources": ["someresources"]}]}]}`, + }, + { + "empty object", + `{}`, + `{}`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rwr := createTestRewriter() + + resBytes, err := RewriteValidatingOrList(rwr.Rules, []byte(tt.manifest), Restore) + require.NoError(t, err, "should rename validating webhook configuration") + + actual := string(resBytes) + require.Equal(t, tt.expect, actual) + }) + } +} diff --git a/images/kube-api-proxy/pkg/rewriter/admission_review.go b/images/kube-api-proxy/pkg/rewriter/admission_review.go new file mode 100644 index 000000000..4ed448f3a --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/admission_review.go @@ -0,0 +1,154 @@ +package rewriter + +import ( + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +// RewriteAdmissionReview rewrites AdmissionReview request and response. +// NOTE: only one rewrite direction is supported for now: +// - Restore object in AdmissionReview request. +// - Do nothing for AdmissionReview response. +func RewriteAdmissionReview(rules *RewriteRules, obj []byte, origGroup string) ([]byte, error) { + response := gjson.GetBytes(obj, "response") + if response.Exists() { + // TODO rewrite response with the Patch. + return obj, nil + } + + request := gjson.GetBytes(obj, "request") + if request.Exists() { + newRequest, err := RestoreAdmissionReviewRequest(rules, []byte(request.Raw), origGroup) + if err != nil { + return nil, err + } + if len(newRequest) > 0 { + obj, err = sjson.SetRawBytes(obj, "request", newRequest) + if err != nil { + return nil, err + } + } + } + + return obj, nil +} + +// RestoreAdmissionReviewRequest restores apiVersion, kind and other fields in an AdmissionReview request. +// Only restoring is required, as AdmissionReview request only comes from API Server. +func RestoreAdmissionReviewRequest(rules *RewriteRules, obj []byte, origGroup string) ([]byte, error) { + var err error + + // Rewrite "resource" field and find rules. + { + resourceObj := gjson.GetBytes(obj, "resource") + group := resourceObj.Get("group") + resource := resourceObj.Get("resource") + // Ignore reviews for unknown renamed group. + if group.String() != rules.RenamedGroup { + return nil, nil + } + newResource := rules.RestoreResource(resource.String()) + obj, err = sjson.SetBytes(obj, "resource.resource", newResource) + if err != nil { + return nil, err + } + obj, err = sjson.SetBytes(obj, "resource.group", origGroup) + if err != nil { + return nil, err + } + } + + // Rewrite "requestResource" field. + { + fieldObj := gjson.GetBytes(obj, "requestResource") + group := fieldObj.Get("group") + resource := fieldObj.Get("resource") + // Ignore reviews for unknown renamed group. + if group.String() != rules.RenamedGroup { + return nil, nil + } + newResource := rules.RestoreResource(resource.String()) + obj, err = sjson.SetBytes(obj, "requestResource.resource", newResource) + if err != nil { + return nil, err + } + obj, err = sjson.SetBytes(obj, "requestResource.group", origGroup) + if err != nil { + return nil, err + } + } + + // Check "subresource" field. No need to rewrite kind, requestKind, object and oldObject fields if subresource is set. + { + fieldObj := gjson.GetBytes(obj, "subresource") + if fieldObj.Exists() && fieldObj.String() != "" { + return obj, err + } + } + + // Rewrite "kind" field. + { + fieldObj := gjson.GetBytes(obj, "kind") + kind := fieldObj.Get("kind") + newKind := rules.RestoreKind(kind.String()) + obj, err = sjson.SetBytes(obj, "kind.kind", newKind) + if err != nil { + return nil, err + } + obj, err = sjson.SetBytes(obj, "kind.group", origGroup) + if err != nil { + return nil, err + } + } + + // Rewrite "requestKind" field. + { + fieldObj := gjson.GetBytes(obj, "requestKind") + kind := fieldObj.Get("kind") + newKind := rules.RestoreKind(kind.String()) + obj, err = sjson.SetBytes(obj, "requestKind.kind", newKind) + if err != nil { + return nil, err + } + obj, err = sjson.SetBytes(obj, "requestKind.group", origGroup) + if err != nil { + return nil, err + } + } + + // Rewrite "object" field. + { + fieldObj := gjson.GetBytes(obj, "object") + if fieldObj.Exists() { + newField, err := RestoreResource(rules, []byte(fieldObj.Raw), origGroup) + if err != nil { + return nil, err + } + if len(newField) > 0 { + obj, err = sjson.SetRawBytes(obj, "object", newField) + if err != nil { + return nil, err + } + } + } + } + + // Rewrite "oldObject" field. + { + fieldObj := gjson.GetBytes(obj, "oldObject") + if fieldObj.Exists() { + newField, err := RestoreResource(rules, []byte(fieldObj.Raw), origGroup) + if err != nil { + return nil, err + } + if len(newField) > 0 { + obj, err = sjson.SetRawBytes(obj, "oldObject", newField) + if err != nil { + return nil, err + } + } + } + } + + return obj, nil +} diff --git a/images/kube-api-proxy/pkg/rewriter/api_endpoint.go b/images/kube-api-proxy/pkg/rewriter/api_endpoint.go new file mode 100644 index 000000000..ea36ddb66 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/api_endpoint.go @@ -0,0 +1,297 @@ +package rewriter + +import ( + "net/url" + "strings" +) + +type APIEndpoint struct { + // IsUknown indicates that path is unknown for rewriter and should be passed as is. + IsUnknown bool + RawPath string + + IsRoot bool + + Prefix string + IsCore bool + + Group string + Version string + Namespace string + ResourceType string + Name string + Subresource string + Remainder []string + + IsCRD bool + CRDResourceType string + CRDGroup string + + IsWatch bool + RawQuery string +} + +// Core resources: +// - /api/VERSION/RESOURCETYPE +// - /api/VERSION/RESOURCETYPE/NAME +// - /api/VERSION/RESOURCETYPE/NAME/SUBRESOURCE +// - /api/VERSION/namespaces/NAMESPACE/RESOURCETYPE +// - /api/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME +// - /api/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE +// - /api/VERSION/namespaces/NAME/SUBRESOURCE - RESOURCETYPE=namespaces +// +// Cluster scoped custom resource: +// - /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE +// | | | | +// PrefixIdx | | | +// GroupIDx -+ | | +// VersionIDx -----+ | +// ClusterResourceIdx -----+ +// +// Namespaced custom resource: +// - /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE +// - /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE +// +// CRD (CRD is itself a cluster scoped custom resource): +// - /apis/apiextensions.k8s.io/v1/customresourcedefinitions +// - /apis/apiextensions.k8s.io/v1/customresourcedefinitions/RESOURCETYPE.GROUP + +const ( + CorePrefix = "api" + APIsPrefix = "apis" + + NamespacesPart = "namespaces" + + CRDGroup = "apiextensions.k8s.io" + CRDResourceType = "customresourcedefinitions" + + WatchClause = "watch=true" +) + +// ParseAPIEndpoint breaks url path by parts. +func ParseAPIEndpoint(apiURL *url.URL) *APIEndpoint { + rawPath := apiURL.Path + rawQuery := apiURL.RawQuery + isWatch := strings.Contains(rawQuery, WatchClause) + + cleanedPath := strings.Trim(apiURL.Path, "/") + pathItems := strings.Split(cleanedPath, "/") + + if len(pathItems) == 0 { + return &APIEndpoint{ + IsRoot: true, + IsWatch: isWatch, + RawPath: rawPath, + RawQuery: rawQuery, + } + } + + var ae *APIEndpoint + // PREFIX is the first item in path. + prefix := pathItems[0] + switch prefix { + case CorePrefix: + ae = parseCoreEndpoint(pathItems) + case APIsPrefix: + ae = parseAPIsEndpoint(pathItems) + } + + if ae == nil { + return &APIEndpoint{ + IsUnknown: true, + RawPath: rawPath, + RawQuery: rawQuery, + } + } + + ae.IsWatch = isWatch + ae.RawPath = rawPath + ae.RawQuery = rawQuery + return ae +} + +func parseCoreEndpoint(pathItems []string) *APIEndpoint { + var isLast bool + var ae APIEndpoint + ae.IsCore = true + + // /api + ae.Prefix, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /api/VERSION + ae.Version, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /api/VERSION/RESOURCETYPE + ae.ResourceType, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /api/VERSION/RESOURCETYPE/NAME + ae.Name, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /api/VERSION/RESOURCETYPE/NAME/SUBRESOURCE + // /api/VERSION/namespaces/NAMESPACE/status + // /api/VERSION/namespaces/NAMESPACE/RESOURCETYPE + ae.Subresource, isLast = Shift(&pathItems) + if ae.ResourceType == NamespacesPart && ae.Subresource != "status" { + // It is a namespaced resource, we got ns name and resourcetype in name and subresource. + ae.Namespace = ae.Name + ae.ResourceType = ae.Subresource + ae.Name = "" + ae.Subresource = "" + } + // Stop if no items available. + if isLast { + return &ae + } + + // /api/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME + ae.Name, isLast = Shift(&pathItems) + if isLast { + return &ae + } + // /api/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE + ae.Subresource, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // Save remaining items if any. + ae.Remainder = pathItems + return &ae +} + +func parseAPIsEndpoint(pathItems []string) *APIEndpoint { + var ae APIEndpoint + var isLast bool + + // /apis + ae.Prefix, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /apis/GROUP + ae.Group, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /apis/GROUP/VERSION + ae.Version, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // /apis/GROUP/VERSION/RESOURCETYPE + ae.ResourceType, isLast = Shift(&pathItems) + // /apis/apiextensions.k8s.io/VERSION/customresourcedefinitions + if ae.Group == CRDGroup && ae.ResourceType == CRDResourceType { + ae.IsCRD = true + } + if isLast { + return &ae + } + + // /apis/GROUP/VERSION/RESOURCETYPE/NAME + ae.Name, isLast = Shift(&pathItems) + if ae.IsCRD { + ae.CRDResourceType, ae.CRDGroup, _ = strings.Cut(ae.Name, ".") + } + if isLast { + return &ae + } + + // /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE + // /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE + ae.Subresource, isLast = Shift(&pathItems) + if ae.ResourceType == NamespacesPart { + // It is a namespaced resource, we got ns name and resourcetype in name and subresource. + ae.Namespace = ae.Name + ae.ResourceType = ae.Subresource + ae.Name = "" + ae.Subresource = "" + } + // Stop if no items available. + if isLast { + return &ae + } + + // /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME + ae.Name, isLast = Shift(&pathItems) + if isLast { + return &ae + } + // /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE + ae.Subresource, isLast = Shift(&pathItems) + if isLast { + return &ae + } + + // Save remaining items if any. + ae.Remainder = pathItems + return &ae +} + +func (a *APIEndpoint) Clone() *APIEndpoint { + clone := *a + return &clone +} + +func (a *APIEndpoint) Path() string { + if a.IsRoot || a.IsCore || a.IsUnknown { + return a.RawPath + } + + ns := "" + if a.Namespace != "" { + ns = NamespacesPart + "/" + a.Namespace + } + var parts []string + parts = []string{ + a.Prefix, + a.Group, + a.Version, + ns, + a.ResourceType, + a.Name, + a.Subresource, + } + if len(a.Remainder) > 0 { + parts = append(parts, a.Remainder...) + } + + nonEmptyParts := make([]string, 0) + for _, part := range parts { + if part != "" { + nonEmptyParts = append(nonEmptyParts, part) + } + } + + return "/" + strings.Join(nonEmptyParts, "/") +} + +// Shift deletes the first item from the array and returns it. +func Shift(items *[]string) (string, bool) { + if len(*items) == 0 { + return "", true + } + + first := (*items)[0] + if len(*items) == 1 { + *items = []string{} + } else { + *items = (*items)[1:] + } + return first, len(*items) == 0 +} diff --git a/images/kube-api-proxy/pkg/rewriter/api_endpoint_test.go b/images/kube-api-proxy/pkg/rewriter/api_endpoint_test.go new file mode 100644 index 000000000..a91d7901a --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/api_endpoint_test.go @@ -0,0 +1,276 @@ +package rewriter + +import ( + "net/url" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseAPIEndpoint(t *testing.T) { + + tests := []struct { + name string + path string + expect *APIEndpoint + }{ + { + "root", + "/", + &APIEndpoint{ + IsRoot: true, + }, + }, + + // Core resources. + { + "core apiversions", + "/api", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + }, + }, + { + "core apiresourcelist", + "/api/v1", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + }, + }, + { + "core deploymentlist", + "/api/v1/deployments", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + ResourceType: "deployments", + }, + }, + { + "core deployment dy name", + "/api/v1/deployments/deployname", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + ResourceType: "deployments", + Name: "deployname", + }, + }, + { + "core deployment status", + "/api/v1/deployments/deployname/status", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + ResourceType: "deployments", + Name: "deployname", + Subresource: "status", + }, + }, + { + "core deployments in nsname", + "/api/v1/namespaces/nsname/deployments", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + ResourceType: "deployments", + Namespace: "nsname", + }, + }, + { + "core deployment in nsname by name", + "/api/v1/namespaces/nsname/deployments/deployname", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + ResourceType: "deployments", + Namespace: "nsname", + Name: "deployname", + }, + }, + { + "core deployment status in nsname", + "/api/v1/namespaces/nsname/deployments/deployname/status", + &APIEndpoint{ + IsCore: true, + Prefix: CorePrefix, + Version: "v1", + ResourceType: "deployments", + Namespace: "nsname", + Name: "deployname", + Subresource: "status", + }, + }, + + // Custom resources. + { + "apigrouplist", + "/apis", + &APIEndpoint{ + Prefix: APIsPrefix, + }, + }, + { + "apigroup", + "/apis/group.io", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + }, + }, + { + "apiresourcelist", + "/apis/group.io/v1", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + }, + }, + { + "someresourceslist", + "/apis/group.io/v1/someresources", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + ResourceType: "someresources", + }, + }, + { + "someresource by name", + "/apis/group.io/v1/someresources/srname", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + ResourceType: "someresources", + Name: "srname", + }, + }, + { + "someresource status", + "/apis/group.io/v1/someresources/srname/status", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + ResourceType: "someresources", + Name: "srname", + Subresource: "status", + }, + }, + { + "someresources in nsname", + "/apis/group.io/v1/namespaces/nsname/someresources", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + Namespace: "nsname", + ResourceType: "someresources", + }, + }, + { + "someresource in nsname by name", + "/apis/group.io/v1/namespaces/nsname/someresources/srname", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + Namespace: "nsname", + ResourceType: "someresources", + Name: "srname", + }, + }, + { + "someresource status in nsname", + "/apis/group.io/v1/namespaces/nsname/someresources/srname/status", + &APIEndpoint{ + Prefix: APIsPrefix, + Group: "group.io", + Version: "v1", + Namespace: "nsname", + ResourceType: "someresources", + Name: "srname", + Subresource: "status", + }, + }, + + // CRDs + { + "crd list", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions", + &APIEndpoint{ + IsCRD: true, + Prefix: APIsPrefix, + Group: "apiextensions.k8s.io", + Version: "v1", + ResourceType: "customresourcedefinitions", + }, + }, + { + "crd by name", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/crname", + &APIEndpoint{ + IsCRD: true, + Prefix: APIsPrefix, + Group: "apiextensions.k8s.io", + Version: "v1", + ResourceType: "customresourcedefinitions", + Name: "crname", + }, + }, + { + "crd status", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/crname/status", + &APIEndpoint{ + IsCRD: true, + Prefix: APIsPrefix, + Group: "apiextensions.k8s.io", + Version: "v1", + ResourceType: "customresourcedefinitions", + Name: "crname", + Subresource: "status", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u, err := url.Parse(tt.path) + require.NoError(t, err, "should parse path '%s'", tt.path) + + actual := ParseAPIEndpoint(u) + if tt.expect == nil { + require.Nil(t, actual, "expect not parse path '%s', got non-empty %+v", tt.path, actual) + } + + if tt.expect != nil { + require.NotNil(t, actual, "expect parse path '%s' to %+v, got nil", tt.path, tt.expect) + + // Flags. + require.Equal(t, tt.expect.IsRoot, actual.IsRoot, "IsRoot") + require.Equal(t, tt.expect.IsCore, actual.IsCore, "IsCore") + require.Equal(t, tt.expect.IsCRD, actual.IsCRD, "IsCRD") + + // Parts. + require.Equal(t, tt.expect.Prefix, actual.Prefix, "Prefix") + require.Equal(t, tt.expect.Group, actual.Group, "Group") + require.Equal(t, tt.expect.Version, actual.Version, "Version") + require.Equal(t, tt.expect.ResourceType, actual.ResourceType, "ResourceType") + require.Equal(t, tt.expect.Name, actual.Name, "Name") + require.Equal(t, tt.expect.Subresource, actual.Subresource, "Subresource") + require.Equal(t, tt.expect.Namespace, actual.Namespace, "Namespace") + } + }) + } +} diff --git a/images/kube-api-proxy/pkg/rewriter/crd.go b/images/kube-api-proxy/pkg/rewriter/crd.go new file mode 100644 index 000000000..2c75bdbd1 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/crd.go @@ -0,0 +1,242 @@ +package rewriter + +import ( + "fmt" + "strings" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +const ( + CRDKind = "CustomResourceDefinition" + CRDListKind = "CustomResourceDefinitionList" +) + +func RewriteCRDOrList(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + // CREATE, UPDATE, or PATCH requests. + if action == Rename { + return RewriteResourceOrList(obj, CRDListKind, func(singleObj []byte) ([]byte, error) { + return RenameCRD(rules, singleObj) + }) + } + + // Responses of GET, LIST, DELETE requests. Also, rewrite in watch events. + return RewriteResourceOrList(obj, CRDListKind, func(singleObj []byte) ([]byte, error) { + return RestoreCRD(rules, singleObj) + }) +} + +// RestoreCRD restores fields in CRD to original. +// +// Example: +// .metadata.name prefixedvirtualmachines.x.virtualization.deckhouse.io -> virtualmachines.kubevirt.io +// .spec.group x.virtualization.deckhouse.io -> kubevirt.io +// .spec.names +// +// categories kubevirt -> all +// kind PrefixedVirtualMachines -> VirtualMachine +// listKind PrefixedVirtualMachineList -> VirtualMachineList +// plural prefixedvirtualmachines -> virtualmachines +// singular prefixedvirtualmachine -> virtualmachine +// shortNames [xvm xvms] -> [vm vms] +func RestoreCRD(rules *RewriteRules, obj []byte) ([]byte, error) { + crdName := gjson.GetBytes(obj, "metadata.name").String() + resource, group, found := strings.Cut(crdName, ".") + if !found { + return nil, fmt.Errorf("malformed CRD name: should be resourcetype.group, got %s", crdName) + } + // Do not restore CRDs in unknown groups. + if group != rules.RenamedGroup { + return nil, nil + } + + origResource := rules.RestoreResource(resource) + + groupRule, resourceRule := rules.GroupResourceRules(origResource) + if resourceRule == nil { + return nil, nil + } + + newName := resourceRule.Plural + "." + groupRule.Group + obj, err := sjson.SetBytes(obj, "metadata.name", newName) + if err != nil { + return nil, err + } + + obj, err = sjson.SetBytes(obj, "spec.group", groupRule.Group) + if err != nil { + return nil, err + } + + names := []byte(gjson.GetBytes(obj, "spec.names").Raw) + + names, err = sjson.SetBytes(names, "categories", rules.RestoreCategories(resourceRule)) + if err != nil { + return nil, err + } + names, err = sjson.SetBytes(names, "kind", rules.RestoreKind(resourceRule.Kind)) + if err != nil { + return nil, err + } + names, err = sjson.SetBytes(names, "listKind", rules.RestoreKind(resourceRule.ListKind)) + if err != nil { + return nil, err + } + names, err = sjson.SetBytes(names, "plural", rules.RestoreResource(resourceRule.Plural)) + if err != nil { + return nil, err + } + names, err = sjson.SetBytes(names, "singular", rules.RestoreResource(resourceRule.Singular)) + if err != nil { + return nil, err + } + names, err = sjson.SetBytes(names, "shortNames", rules.RestoreShortNames(resourceRule.ShortNames)) + if err != nil { + return nil, err + } + + obj, err = sjson.SetRawBytes(obj, "spec.names", names) + if err != nil { + return nil, err + } + + return obj, nil +} + +// RenameCRD renames fields in CRD. +// +// Example: +// .metadata.name virtualmachines.kubevirt.io -> prefixedvirtualmachines.x.virtualization.deckhouse.io +// .spec.group kubevirt.io -> x.virtualization.deckhouse.io +// .spec.names +// +// categories all -> kubevirt +// kind VirtualMachine -> PrefixedVirtualMachines +// listKind VirtualMachineList -> PrefixedVirtualMachineList +// plural virtualmachines -> prefixedvirtualmachines +// singular virtualmachine -> prefixedvirtualmachine +// shortNames [vm vms] -> [xvm xvms] +func RenameCRD(rules *RewriteRules, obj []byte) ([]byte, error) { + crdName := gjson.GetBytes(obj, "metadata.name").String() + resource, group, found := strings.Cut(crdName, ".") + if !found { + return nil, fmt.Errorf("malformed CRD name: should be resourcetype.group, got %s", crdName) + } + + _, resourceRule := rules.ResourceRules(group, resource) + if resourceRule == nil { + return nil, nil + } + + newName := rules.RenameResource(resource) + "." + rules.RenamedGroup + obj, err := sjson.SetBytes(obj, "metadata.name", newName) + if err != nil { + return nil, err + } + + spec := gjson.GetBytes(obj, "spec") + newSpec, err := renameCRDSpec(rules, resourceRule, []byte(spec.Raw)) + if err != nil { + return nil, err + } + return sjson.SetRawBytes(obj, "spec", newSpec) +} + +func renameCRDSpec(rules *RewriteRules, resourceRule *ResourceRule, spec []byte) ([]byte, error) { + var err error + + spec, err = sjson.SetBytes(spec, "group", rules.RenamedGroup) + if err != nil { + return nil, err + } + + // Rename fields in the 'names' object. + names := []byte(gjson.GetBytes(spec, "names").Raw) + + if gjson.GetBytes(names, "categories").Exists() { + names, err = sjson.SetBytes(names, "categories", rules.RenameCategories(resourceRule.Categories)) + if err != nil { + return nil, err + } + } + if gjson.GetBytes(names, "kind").Exists() { + names, err = sjson.SetBytes(names, "kind", rules.RenameKind(resourceRule.Kind)) + if err != nil { + return nil, err + } + } + if gjson.GetBytes(names, "listKind").Exists() { + names, err = sjson.SetBytes(names, "listKind", rules.RenameKind(resourceRule.ListKind)) + if err != nil { + return nil, err + } + } + if gjson.GetBytes(names, "plural").Exists() { + names, err = sjson.SetBytes(names, "plural", rules.RenameResource(resourceRule.Plural)) + if err != nil { + return nil, err + } + } + if gjson.GetBytes(names, "singular").Exists() { + names, err = sjson.SetBytes(names, "singular", rules.RenameResource(resourceRule.Singular)) + if err != nil { + return nil, err + } + } + if gjson.GetBytes(names, "shortNames").Exists() { + names, err = sjson.SetBytes(names, "shortNames", rules.RenameShortNames(resourceRule.ShortNames)) + if err != nil { + return nil, err + } + } + + spec, err = sjson.SetRawBytes(spec, "names", names) + if err != nil { + return nil, err + } + + return spec, nil +} + +func RenameCRDPatch(rules *RewriteRules, resourceRule *ResourceRule, obj []byte) ([]byte, error) { + var err error + + patches := gjson.ParseBytes(obj).Array() + if len(patches) == 0 { + return obj, nil + } + + newPatches := []byte(`[]`) + isRenamed := false + for _, patch := range patches { + newPatch := []byte(patch.Raw) + + op := gjson.GetBytes(newPatch, "op").String() + path := gjson.GetBytes(newPatch, "path").String() + + if (op == "replace" || op == "add") && path == "/spec" { + isRenamed = true + value := []byte(gjson.GetBytes(newPatch, "value").Raw) + newValue, err := renameCRDSpec(rules, resourceRule, value) + if err != nil { + return nil, err + } + newPatch, err = sjson.SetRawBytes(newPatch, "value", newValue) + if err != nil { + return nil, err + } + } + + newPatches, err = sjson.SetRawBytes(newPatches, "-1", newPatch) + if err != nil { + return nil, err + } + } + + if !isRenamed { + return obj, nil + } + + return newPatches, nil +} diff --git a/images/kube-api-proxy/pkg/rewriter/crd_test.go b/images/kube-api-proxy/pkg/rewriter/crd_test.go new file mode 100644 index 000000000..e2691d826 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/crd_test.go @@ -0,0 +1,319 @@ +package rewriter + +import ( + "bufio" + "bytes" + "fmt" + "net/http" + "strings" + "testing" + + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +func createRewriterForCRDTest() *RuleBasedRewriter { + apiGroupRules := map[string]APIGroupRule{ + "original.group.io": { + GroupRule: GroupRule{ + Group: "original.group.io", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + }, + ResourceRules: map[string]ResourceRule{ + "someresources": { + Kind: "SomeResource", + ListKind: "SomeResourceList", + Plural: "someresources", + Singular: "someresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"sr", "srs"}, + }, + "anotherresources": { + Kind: "AnotherResource", + ListKind: "AnotherResourceList", + Plural: "anotherresources", + Singular: "anotherresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + ShortNames: []string{"ar"}, + }, + }, + }, + "other.group.io": { + GroupRule: GroupRule{ + Group: "original.group.io", + Versions: []string{"v2alpha3"}, + PreferredVersion: "v2alpha3", + }, + ResourceRules: map[string]ResourceRule{ + "otherresources": { + Kind: "OtherResource", + ListKind: "OtherResourceList", + Plural: "otherresources", + Singular: "otherresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + ShortNames: []string{"or"}, + }, + }, + }, + } + + rwRules := &RewriteRules{ + KindPrefix: "Prefixed", // KV + ResourceTypePrefix: "prefixed", // kv + ShortNamePrefix: "p", + Categories: []string{"prefixed"}, + RenamedGroup: "prefixed.resources.group.io", + Rules: apiGroupRules, + } + + return &RuleBasedRewriter{ + Rules: rwRules, + } +} + +// TestCRDRename - rename of a single CRD. +func TestCRDRename(t *testing.T) { + origGroup := "original.group.io" + reqBody := `{ +"apiVersion": "apiextensions.k8s.io/v1", +"kind": "CustomResourceDefinition", +"metadata": { + "name":"someresources.original.group.io" +} +"spec": { + "group": "original.group.io", + "names": { + "kind": "SomeResource", + "listKind": "SomeResourceList", + "plural": "someresources", + "singular": "someresource", + "shortNames": ["sr"], + "categories": ["all"] + }, + "scope":"Namespaced", + "versions": {} +} +}` + rwr := createRewriterForCRDTest() + testCRDRules := rwr.Rules + + restored, err := RewriteCRDOrList(testCRDRules, []byte(reqBody), Rename) + if err != nil { + t.Fatalf("should rename CRD without error: %v", err) + } + if restored == nil { + t.Fatalf("should rename CRD: %v", err) + } + + resRule := testCRDRules.Rules[origGroup].ResourceRules["someresources"] + + tests := []struct { + path string + expected string + }{ + {"metadata.name", testCRDRules.RenameResource(resRule.Plural) + "." + testCRDRules.RenamedGroup}, + {"spec.group", testCRDRules.RenamedGroup}, + {"spec.names.kind", testCRDRules.RenameKind(resRule.Kind)}, + {"spec.names.listKind", testCRDRules.RenameKind(resRule.ListKind)}, + {"spec.names.plural", testCRDRules.RenameResource(resRule.Plural)}, + {"spec.names.singular", testCRDRules.RenameResource(resRule.Singular)}, + {"spec.names.shortNames", `["psr","psrs"]`}, + } + + for _, tt := range tests { + t.Run(tt.path, func(t *testing.T) { + actual := gjson.GetBytes(restored, tt.path).String() + if actual != tt.expected { + t.Fatalf("%s value should be %s, got %s", tt.path, tt.expected, actual) + } + }) + } +} + +// TestCRDPatch tests renaming /spec in a CRD patch. +func TestCRDPatch(t *testing.T) { + patches := `[{ "op": "add", "path": "/metadata/ownerReferences", "value": null }, +{ "op": "replace", "path": "/spec", "value": { +"group":"original.group.io", +"names":{"plural":"someresources","singular":"someresource","shortNames":["sr","srs"],"kind":"SomeResource","categories":["all"]}, +"scope":"Namespaced","versions":[{"name":"v1alpha1","schema":{}}] +} } +]` + patches = strings.ReplaceAll(patches, "\n", "") + + expect := `[{ "op": "add", "path": "/metadata/ownerReferences", "value": null }, +{ "op": "replace", "path": "/spec", "value": { +"group":"prefixed.resources.group.io", +"names":{"plural":"prefixedsomeresources","singular":"prefixedsomeresource","shortNames":["psr","psrs"],"kind":"PrefixedSomeResource","categories":["prefixed"]}, +"scope":"Namespaced","versions":[{"name":"v1alpha1","schema":{}}] +} } +]` + expect = strings.ReplaceAll(expect, "\n", "") + + rwr := createRewriterForCRDTest() + _, resRule := rwr.Rules.ResourceRules("original.group.io", "someresources") + require.NotNil(t, resRule, "should get resource rule for hardcoded group and resourceType") + + resBytes, err := RenameCRDPatch(rwr.Rules, resRule, []byte(patches)) + require.NoError(t, err, "should rename CRD patch") + + actual := string(resBytes) + require.Equal(t, expect, actual) +} + +// TestCRDRestore test restoring of a single CRD. +func TestCRDRestore(t *testing.T) { + crdHTTPRequest := `GET /apis/apiextensions.k8s.io/v1/customresourcedefinitions/someresources.original.group.io HTTP/1.1 +Host: 127.0.0.1 + +` + origGroup := "original.group.io" + crdPayload := `{ +"apiVersion": "apiextensions.k8s.io/v1", +"kind": "CustomResourceDefinition", +"metadata": { + "name":"prefixedsomeresources.prefixed.resources.group.io" +} +"spec": { + "group": "prefixed.resources.group.io", + "names": { + "kind": "PrefixedSomeResource", + "listKind": "PrefixedSomeResourceList", + "plural": "prefixedsomeresources", + "singular": "prefixedsomeresource", + "shortNames": ["psr"], + "categories": ["prefixed"] + }, + "scope":"Namespaced", + "versions": {} +} +}` + + req, err := http.ReadRequest(bufio.NewReader(bytes.NewBufferString(crdHTTPRequest))) + require.NoError(t, err, "should parse hardcoded http request") + require.NotNil(t, req.URL, "should parse url in hardcoded http request") + + rwr := createRewriterForCRDTest() + targetReq := NewTargetRequest(rwr, req) + require.NotNil(t, targetReq, "should get TargetRequest") + require.Equal(t, origGroup, targetReq.OrigGroup(), "should set proper orig group") + + resultBytes, err := rwr.RewriteJSONPayload(targetReq, []byte(crdPayload), Restore) // RewriteCRDOrList(crdPayload, []byte(reqBody), Restore, origGroup) + if err != nil { + t.Fatalf("should restore CRD without error: %v", err) + } + if resultBytes == nil { + t.Fatalf("should restore CRD: %v", err) + } + + resRule := rwr.Rules.Rules[origGroup].ResourceRules["someresources"] + + tests := []struct { + path string + expected string + }{ + {"metadata.name", resRule.Plural + "." + origGroup}, + {"spec.group", origGroup}, + {"spec.names.kind", resRule.Kind}, + {"spec.names.listKind", resRule.ListKind}, + {"spec.names.plural", resRule.Plural}, + {"spec.names.singular", resRule.Singular}, + } + + for _, tt := range tests { + t.Run(tt.path, func(t *testing.T) { + actual := gjson.GetBytes(resultBytes, tt.path).String() + if actual != tt.expected { + t.Fatalf("%s value should be %s, got %s", tt.path, tt.expected, actual) + } + }) + } +} + +func TestCRDPathRewrite(t *testing.T) { + tests := []struct { + name string + urlPath string + expected string + origGroup string + origResourceType string + }{ + { + "crd with rule", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/someresources.original.group.io", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/prefixedsomeresources.prefixed.resources.group.io", + "original.group.io", + "someresources", + }, + { + "crd watch by name", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions?fieldSelector=metadata.name%3Dsomeresources.original.group.io&resourceVersion=0&watch=true", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions?fieldSelector=metadata.name%3Dprefixedsomeresources.prefixed.resources.group.io&resourceVersion=0&watch=true", + "", + "", + }, + { + "unknown crd watch by name", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions?fieldSelector=metadata.name%3Dresource.unknown.group.io&resourceVersion=0&watch=true", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions?fieldSelector=metadata.name%3Dresource.unknown.group.io&resourceVersion=0&watch=true", + "", + "", + }, + { + "crd without rule", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/unknown.group.io", + "", + "", + "", + }, + { + "crd list", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions", + "", + "", + "", + }, + { + "non crd apiextension", + "/apis/apiextensions.k8s.io/v1/unknown", + "", + "", + "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + httpReqHead := fmt.Sprintf(`GET %s HTTP/1.1`, tt.urlPath) + httpReq := httpReqHead + "\n" + "Host: 127.0.0.1\n\n" + req, err := http.ReadRequest(bufio.NewReader(bytes.NewBufferString(httpReq))) + require.NoError(t, err, "should parse hardcoded http request") + require.NotNil(t, req.URL, "should parse url in hardcoded http request") + + rwr := createRewriterForCRDTest() + targetReq := NewTargetRequest(rwr, req) + require.NotNil(t, targetReq, "should get TargetRequest") + + if tt.expected == "" { + require.Equal(t, tt.urlPath, targetReq.Path(), "should not rewrite api endpoint path") + return + } + + if tt.origGroup != "" { + require.Equal(t, tt.origGroup, targetReq.OrigGroup()) + } + + actual := targetReq.Path() + if targetReq.RawQuery() != "" { + actual += "?" + targetReq.RawQuery() + } + + require.Equal(t, tt.expected, actual, "should rewrite api endpoint path") + }) + } +} diff --git a/images/kube-api-proxy/pkg/rewriter/discovery.go b/images/kube-api-proxy/pkg/rewriter/discovery.go new file mode 100644 index 000000000..f346bcc69 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/discovery.go @@ -0,0 +1,259 @@ +package rewriter + +import ( + "fmt" + "strings" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" + "k8s.io/apimachinery/pkg/runtime" +) + +// RewriteAPIGroupList restores groups and kinds in /apis/ response. +// +// Rewrite each APIGroup in "groups". +// Response example: +// {"name":"x.virtualization.deckhouse.io", +// +// "versions":[ +// {"groupVersion":"x.virtualization.deckhouse.io/v1","version":"v1"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1beta1","version":"v1beta1"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1alpha3","version":"v1alpha3"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1alpha2","version":"v1alpha2"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1alpha1","version":"v1alpha1"} +// ], +// "preferredVersion":{"groupVersion":"x.virtualization.deckhouse.io/v1","version":"v1"} +// } +func RewriteAPIGroupList(rules *RewriteRules, objBytes []byte) ([]byte, error) { + groups := gjson.GetBytes(objBytes, "groups").Array() + // TODO get rid of RawExtension, use SetRawBytes. + rwrGroups := make([]interface{}, 0) + for _, group := range groups { + groupName := gjson.Get(group.Raw, "name").String() + // Replace renamed group with groups from rules. + if groupName == rules.RenamedGroup { + rwrGroups = append(rwrGroups, rules.GetAPIGroupList()...) + continue + } + rwrGroups = append(rwrGroups, runtime.RawExtension{Raw: []byte(group.Raw)}) + } + + return sjson.SetBytes(objBytes, "groups", rwrGroups) +} + +// RewriteAPIGroup rewrites responses for +// /apis/x.virtualization.deckhouse.io +// +// This call returns all versions for x.virtualization.deckhouse.io. +// Rewriter should reduce versions for only available in original group +// To reduce further requests with specific versions. +// +// Example response: +// { "kind":"APIGroup", +// +// "apiVersion":"v1", +// "name":"x.virtualization.deckhouse.io", +// "versions":[ +// {"groupVersion":"x.virtualization.deckhouse.io/v1","version":"v1"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1beta1","version":"v1beta1"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1alpha3","version":"v1alpha3"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1alpha2","version":"v1alpha2"}, +// {"groupVersion":"x.virtualization.deckhouse.io/v1alpha1","version":"v1alpha1"} +// ], +// "preferredVersion": { +// "groupVersion":"x.virtualization.deckhouse.io/v1", +// "version":"v1"} +// } +// +// Rewrite for kubevirt.io group should be: +// { "kind":"APIGroup", +// +// "apiVersion":"v1", +// "name":"kubevirt.io", +// "versions":[ +// {"groupVersion":"kubevirt.io/v1","version":"v1"}, +// {"groupVersion":"kubevirt.io/v1alpha3","version":"v1alpha3"} +// ], +// "preferredVersion": { +// "groupVersion":"kubevirt.io/v1", +// "version":"v1"} +// } +// +// And rewrite for clone.kubevirt.io group should be: +// { "kind":"APIGroup", +// +// "apiVersion":"v1", +// "name":"clone.kubevirt.io", +// "versions":[ +// {"groupVersion":"clone.kubevirt.io/v1alpha1","version":"v1alpha1"} +// ], +// "preferredVersion": { +// "groupVersion":"clone.kubevirt.io/v1alpha1", +// "version":"v1alpha1"} +// } +func RewriteAPIGroup(rules *RewriteRules, obj []byte, origGroup string) ([]byte, error) { + apiGroupRule, ok := rules.Rules[origGroup] + if !ok { + return nil, fmt.Errorf("no APIGroup rewrites for group '%s'", origGroup) + } + + // Grab all versions from rules. + versions := make([]interface{}, 0) + for _, ver := range apiGroupRule.GroupRule.Versions { + versions = append(versions, map[string]interface{}{ + "groupVersion": origGroup + "/" + ver, + "version": ver, + }) + } + preferredVersion := map[string]interface{}{ + "groupVersion": origGroup + "/" + apiGroupRule.GroupRule.PreferredVersion, + "version": apiGroupRule.GroupRule.PreferredVersion, + } + + obj, err := sjson.SetBytes(obj, "name", origGroup) + if err != nil { + return nil, err + } + obj, err = sjson.SetBytes(obj, "versions", versions) + if err != nil { + return nil, err + } + obj, err = sjson.SetBytes(obj, "preferredVersion", preferredVersion) + if err != nil { + return nil, err + } + return obj, nil +} + +// RewriteAPIResourceList rewrites server responses on +// /apis/GROUP/VERSION requests. +// This method excludes resources not belonging to original group from request. +// +// Example: +// +// Path rewrite: https://10.222.0.1:443/apis/kubevirt.io/v1 -> https://10.222.0.1:443/apis/x.virtualization.deckhouse.io/v1 +// original Group: kubevirt.io +// rewrite name,singularName,kind for each resource. +// /status -> name and kind +// /scale -> rewrite resource name in the name field +// +// Response from /apis/x.virtualization.deckhouse.io/v1: +// +// { +// "kind":"APIResourceList", +// "apiVersion":"v1", +// +// --> "groupVersion":"x.virtualization.deckhouse.io/v1" --> rewrite to origGroup+version: kubevirt.io/v1 +// +// "resources":[ +// { +// +// --> "name":"virtualmachineinstancereplicasets", +// --> "singularName":"virtualmachineinstancereplicaset", +// +// "namespaced":true, +// +// --> "kind":"VirtualMachineInstanceReplicaSet", +// +// "verbs":["delete","deletecollection","get","list","patch","create","update","watch"], +// "shortNames":["xvmirs","xvmirss"], +// "categories":["kubevirt"], +// "storageVersionHash":"QUMxLW9gfYs=" +// },{ +// +// --> "name":"virtualmachineinstancereplicasets/status", +// +// "singularName":"", +// "namespaced":true, +// +// --> "kind":"VirtualMachineInstanceReplicaSet", +// +// "verbs":["get","patch","update"] +// },{ +// +// --> "name":"virtualmachineinstancereplicasets/scale", +// +// "singularName":"", +// "namespaced":true, +// "group":"autoscaling", +// "version":"v1", +// "kind":"Scale", +// "verbs":["get","patch","update"] +// }] +// } +func RewriteAPIResourceList(rules *RewriteRules, obj []byte, origGroup string) ([]byte, error) { + // Ignore apiGroups not in rules. + apiGroupRule, ok := rules.Rules[origGroup] + if !ok { + return obj, nil + } + // MVP: rewrite only group for now. (No prefixes in the cluster yet). + obj, err := sjson.SetBytes(obj, "groupVersion", origGroup+"/"+apiGroupRule.GroupRule.PreferredVersion) + if err != nil { + return nil, err + } + + resources := []byte(`[]`) + + for _, resource := range gjson.GetBytes(obj, "resources").Array() { + name := resource.Get("name").String() + nameParts := strings.Split(name, "/") + resourceName := rules.RestoreResource(nameParts[0]) + + _, resourceRule := rules.ResourceRules(origGroup, resourceName) + if resourceRule == nil { + continue + } + + // Rewrite name and kind. + resBytes, err := sjson.SetBytes([]byte(resource.Raw), "name", rules.RestoreResource(name)) + if err != nil { + return nil, err + } + + kind := gjson.GetBytes(resBytes, "kind").String() + if kind != "" { + resBytes, err = sjson.SetBytes(resBytes, "kind", rules.RestoreKind(kind)) + if err != nil { + return nil, err + } + } + + singular := gjson.GetBytes(resBytes, "singularName").String() + if singular != "" { + resBytes, err = sjson.SetBytes(resBytes, "singularName", rules.RestoreResource(singular)) + if err != nil { + return nil, err + } + } + + shortNames := gjson.GetBytes(resBytes, "shortNames").Array() + if len(shortNames) > 0 { + strShortNames := make([]string, 0, len(shortNames)) + for _, shortName := range shortNames { + strShortNames = append(strShortNames, shortName.String()) + } + newShortNames := rules.RestoreShortNames(strShortNames) + resBytes, err = sjson.SetBytes(resBytes, "shortNames", newShortNames) + if err != nil { + return nil, err + } + } + + categories := gjson.GetBytes(resBytes, "categories") + if categories.Exists() { + restoredCategories := rules.RestoreCategories(resourceRule) + resBytes, err = sjson.SetBytes(resBytes, "categories", restoredCategories) + if err != nil { + return nil, err + } + } + + resources, err = sjson.SetRawBytes(resources, "-1", resBytes) + if err != nil { + return nil, err + } + } + + return sjson.SetRawBytes(obj, "resources", resources) +} diff --git a/images/kube-api-proxy/pkg/rewriter/discovery_test.go b/images/kube-api-proxy/pkg/rewriter/discovery_test.go new file mode 100644 index 000000000..7b87ce72f --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/discovery_test.go @@ -0,0 +1,285 @@ +package rewriter + +import ( + "bufio" + "bytes" + "net/http" + "strconv" + "testing" + + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +func createRewriterForDiscoveryTest() *RuleBasedRewriter { + apiGroupRules := map[string]APIGroupRule{ + "original.group.io": { + GroupRule: GroupRule{ + Group: "original.group.io", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + }, + ResourceRules: map[string]ResourceRule{ + "someresources": { + Kind: "SomeResource", + ListKind: "SomeResourceList", + Plural: "someresources", + Singular: "someresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"sr", "srs"}, + }, + "anotherresources": { + Kind: "AnotherResource", + ListKind: "AnotherResourceList", + Plural: "anotherresources", + Singular: "anotherresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + ShortNames: []string{"ar"}, + }, + }, + }, + "other.group.io": { + GroupRule: GroupRule{ + Group: "original.group.io", + Versions: []string{"v2alpha3"}, + PreferredVersion: "v2alpha3", + }, + ResourceRules: map[string]ResourceRule{ + "otherresources": { + Kind: "OtherResource", + ListKind: "OtherResourceList", + Plural: "otherresources", + Singular: "otherresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + ShortNames: []string{"or"}, + }, + }, + }, + } + + webhookRules := map[string]WebhookRule{ + "/validate-prefixed-resources-group-io-v1-prefixedsomeresource": { + Path: "/validate-original-group-io-v1-someresource", + Group: "original.group.io", + Resource: "someresources", + }, + } + + rwRules := &RewriteRules{ + KindPrefix: "Prefixed", // KV + ResourceTypePrefix: "prefixed", // kv + ShortNamePrefix: "p", + Categories: []string{"prefixed"}, + RenamedGroup: "prefixed.resources.group.io", + Rules: apiGroupRules, + Webhooks: webhookRules, + } + + return &RuleBasedRewriter{ + Rules: rwRules, + } +} + +func TestRewriteRequestAPIResourceList(t *testing.T) { + // Request APIResourcesList of original, non-renamed resources. + request := `GET /apis/original.group.io/v1 HTTP/1.1 +Host: 127.0.0.1 + +` + req, err := http.ReadRequest(bufio.NewReader(bytes.NewBufferString(request))) + require.NoError(t, err, "should read hardcoded request") + + expectPath := "/apis/prefixed.resources.group.io/v1" + + // Response body with renamed APIResourcesList + resourceListPayload := `{ + "kind": "APIResourceList", + "apiVersion": "v1", + "groupVersion": "prefixed.resources.group.io/v1", + "resources": [ + {"name":"prefixedsomeresources", + "singularName":"prefixedsomeresource", + "namespaced":true, + "kind":"PrefixedSomeResource", + "verbs":["delete","deletecollection","get","list","patch","create","update","watch"], + "shortNames":["psr","psrs"], + "categories":["prefixed"], + "storageVersionHash":"1qIJ90Mhvd8="}, + + {"name":"prefixedsomeresources/status", + "singularName":"", + "namespaced":true, + "kind":"PrefixedSomeResource", + "verbs":["get","patch","update"]}, + + {"name":"prefixedotherresources", + "singularName":"prefixedotherresource", + "namespaced":true, + "kind":"PrefixedOtherResource", + "verbs":["delete","deletecollection","get","list","patch","create","update","watch"], + "shortNames":["por"], + "categories":["prefixed"], + "storageVersionHash":"Nwlto9QquX0="}, + + {"name":"prefixedotherresources/status", + "singularName":"", + "namespaced":true, + "kind":"PrefixOtherResource", + "verbs":["get","patch","update"]} +]}` + + // Client proxy mode. + rwr := createRewriterForDiscoveryTest() + + var targetReq *TargetRequest + + targetReq = NewTargetRequest(rwr, req) + require.NotNil(t, targetReq, "should get TargetRequest") + require.Equal(t, expectPath, targetReq.Path(), "should rewrite api endpoint path") + + resultBytes, err := rwr.RewriteJSONPayload(targetReq, []byte(resourceListPayload), Restore) + if err != nil { + t.Fatalf("should rewrite body with renamed resources: %v", err) + } + + actual := string(resultBytes) + + require.Contains(t, actual, `"someresources"`, "should contains original someresources, got: %s", actual) + require.Contains(t, actual, `"someresources/status"`, "should contains original someresources/status, got: %s", actual) + require.NotContains(t, actual, `"otherresources"`, "should not contains not requested otherresources, got: %s", actual) + require.NotContains(t, actual, `"otherresources/status"`, "should not contains not requested otherresources/status, got: %s", actual) +} + +func TestRewriteAdmissionReviewRequestForResource(t *testing.T) { + admissionReview := `{ + "kind":"AdmissionReview", + "apiVersion":"admission.k8s.io/v1", + "request":{ + "uid":"389cfe15-34a1-4829-ad4d-de2576385711", + "kind":{"group":"prefixed.resources.group.io","version":"v1","kind":"PrefixedSomeResource"}, + "resource":{"group":"prefixed.resources.group.io","version":"v1","resource":"prefixedsomeresources"}, + "requestKind":{"group":"prefixed.resources.group.io","version":"v1","kind":"PrefixedSomeResource"}, + "requestResource":{"group":"prefixed.resources.group.io","version":"v1","resource":"prefixedsomeresources"}, + "name":"some-resource-name", + "namespace":"nsname", + "operation":"UPDATE", + "userInfo":{"username":"kubernetes-admin","groups":["system:masters","system:authenticated"]}, + "object":{ + "apiVersion":"prefixed.resources.group.io/v1", + "kind":"PrefixedSomeResource", + "metadata":{ + "annotations":{ + "anno":"value", + }, + "creationTimestamp":"2024-02-05T12:42:32Z", + "finalizers":["group.io/protection","other.group.io/protection"], + "name":"some-resource-name", + "namespace":"nsname", + "ownerReferences":[ + {"apiVersion":"controller.group.io/v2", + "blockOwnerDeletion":true, + "controller":true, + "kind":"SomeKind","name":"some-controller-name","uid":"904cfea9-c9d6-4d3a-82f7-5790b1a1b3e0"} + ], + "resourceVersion":"265111919","uid":"4c74c3ff-2199-4f20-a71c-3b0e5fb505ca" + }, + "spec":{"field1":"value1", "field2":"value2"}, + "status":{ + "conditions":[ + {"lastProbeTime":null,"lastTransitionTime":"2024-03-06T14:38:39Z","status":"True","type":"Ready"}, + {"lastProbeTime":"2024-02-29T14:11:05Z","lastTransitionTime":null,"status":"True","type":"Healthy"}], + "printableStatus":"Ready" + } + }, + + "oldObject":{ + "apiVersion":"prefixed.resources.group.io/v1", + "kind":"PrefixedSomeResource", + "metadata":{ + "annotations":{ + "anno":"value", + }, + "creationTimestamp":"2024-02-05T12:42:32Z", + "finalizers":["group.io/protection","other.group.io/protection"], + "name":"some-resource-name", + "namespace":"nsname", + "ownerReferences":[ + {"apiVersion":"controller.group.io/v2", + "blockOwnerDeletion":true, + "controller":true, + "kind":"SomeKind","name":"some-controller-name","uid":"904cfea9-c9d6-4d3a-82f7-5790b1a1b3e0"} + ], + "resourceVersion":"265111919","uid":"4c74c3ff-2199-4f20-a71c-3b0e5fb505ca" + }, + "spec":{"field1":"value1", "field2":"value2"}, + "status":{ + "conditions":[ + {"lastProbeTime":null,"lastTransitionTime":"2024-03-06T14:38:39Z","status":"True","type":"Ready"}, + {"lastProbeTime":"2024-02-29T14:11:05Z","lastTransitionTime":null,"status":"True","type":"Healthy"}], + "printableStatus":"Ready" + } + } + } +} +` + admissionReviewRequest := `POST /validate-prefixed-resources-group-io-v1-prefixedsomeresource HTTP/1.1 +Host: 127.0.0.1 +Content-Type: application/json +Content-Length: ` + strconv.Itoa(len(admissionReview)) + ` + +` + admissionReview + + req, err := http.ReadRequest(bufio.NewReader(bytes.NewBufferString(admissionReviewRequest))) + require.NoError(t, err, "should read hardcoded AdmissionReview request") + + rwr := createRewriterForDiscoveryTest() + + // Check getting TargetRequest from the webhook request. + var targetReq *TargetRequest + targetReq = NewTargetRequest(rwr, req) + require.NotNil(t, targetReq, "should get TargetRequest") + require.True(t, targetReq.ShouldRewriteRequest(), "should rewrite request in TargetRequest") + + // Check payload rewriting. + resultBytes, err := rwr.RewriteJSONPayload(targetReq, []byte(admissionReview), Restore) + require.NoError(t, err, "should rewrite request") + if err != nil { + t.Fatalf("should rewrite request: %v", err) + } + + require.Greater(t, len(resultBytes), 0, "result bytes from RewriteJSONPayload should not be empty") + + groupRule, resRule := rwr.Rules.ResourceRules("original.group.io", "someresources") + require.NotNil(t, resRule, "should get resourceRule for hardcoded group and resourceType") + + tests := []struct { + path string + expected string + }{ + {"request.kind.group", groupRule.Group}, + {"request.kind.kind", resRule.Kind}, + {"request.requestKind.group", groupRule.Group}, + {"request.requestKind.kind", resRule.Kind}, + {"request.resource.group", groupRule.Group}, + {"request.resource.resource", resRule.Plural}, + {"request.requestResource.group", groupRule.Group}, + {"request.requestResource.resource", resRule.Plural}, + {"request.object.apiVersion", groupRule.Group + "/v1"}, + {"request.object.kind", resRule.Kind}, + {"request.oldObject.apiVersion", groupRule.Group + "/v1"}, + {"request.oldObject.kind", resRule.Kind}, + } + + for _, tt := range tests { + t.Run(tt.path, func(t *testing.T) { + actual := gjson.GetBytes(resultBytes, tt.path).String() + if actual != tt.expected { + t.Fatalf("%s value should be %s, got %s", tt.path, tt.expected, actual) + } + }) + } +} diff --git a/images/kube-api-proxy/pkg/rewriter/list.go b/images/kube-api-proxy/pkg/rewriter/list.go new file mode 100644 index 000000000..12823695f --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/list.go @@ -0,0 +1,43 @@ +package rewriter + +import ( + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +// RewriteResourceOrList is a helper to transform a single resource or a list of resources. +func RewriteResourceOrList(payload []byte, listKind string, transformFn func(singleObj []byte) ([]byte, error)) ([]byte, error) { + kind := gjson.GetBytes(payload, "kind").String() + + // Not a list, transform a single resource. + if kind != listKind { + return transformFn(payload) + } + + return RewriteArray(payload, "items", transformFn) +} + +func RewriteArray(obj []byte, arrayPath string, transformFn func(item []byte) ([]byte, error)) ([]byte, error) { + // Transform each item in list. Put back original items if transformFn returns nil bytes. + items := gjson.GetBytes(obj, arrayPath).Array() + if len(items) == 0 { + return obj, nil + } + rwrItems := []byte(`[]`) + for _, item := range items { + rwrItem, err := transformFn([]byte(item.Raw)) + if err != nil { + return nil, err + } + // Put original item back. + if rwrItem == nil { + rwrItem = []byte(item.Raw) + } + rwrItems, err = sjson.SetRawBytes(rwrItems, "-1", rwrItem) + if err != nil { + return nil, err + } + } + + return sjson.SetRawBytes(obj, arrayPath, rwrItems) +} diff --git a/images/kube-api-proxy/pkg/rewriter/load.go b/images/kube-api-proxy/pkg/rewriter/load.go new file mode 100644 index 000000000..4621678a7 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/load.go @@ -0,0 +1,22 @@ +package rewriter + +import ( + "os" + + "sigs.k8s.io/yaml" +) + +func LoadRules(filename string) (*RewriteRules, error) { + data, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + + var rules = new(RewriteRules) + err = yaml.Unmarshal(data, rules) + if err != nil { + return nil, err + } + + return rules, nil +} diff --git a/images/kube-api-proxy/pkg/rewriter/path.go b/images/kube-api-proxy/pkg/rewriter/path.go new file mode 100644 index 000000000..364e793e6 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/path.go @@ -0,0 +1,175 @@ +package rewriter + +// RewritePath return rewritten TargetPath along with original group and resource type. +// TODO: this rewriter is not conform to S in SOLID. Should split to ParseAPIEndpoint and RewriteAPIEndpoint. +//func (rw *RuleBasedRewriter) RewritePath(urlPath string) (*TargetRequest, error) { +// // Is it a webhook? +// if webhookRule, ok := rw.Rules.Webhooks[urlPath]; ok { +// return &TargetRequest{ +// Webhook: &webhookRule, +// }, nil +// } +// +// // Is it an API request? +// if strings.HasPrefix(urlPath, "/apis/") || urlPath == "/apis" { +// // TODO refactor RewriteAPIPath to produce a TargetPath, not an array in PathItems. +// cleanedPath := strings.Trim(urlPath, "/") +// pathItems := strings.Split(cleanedPath, "/") +// +// // First, try to rewrite CRD request. +// res := RewriteCRDPath(pathItems, rw.Rules) +// if res != nil { +// return res, nil +// } +// // Next, rewrite usual request. +// res, err := RewriteAPIsPath(pathItems, rw.Rules) +// if err != nil { +// return nil, err +// } +// if res == nil { +// // e.g. no rewrite rule find. +// return nil, nil +// } +// if len(res.PathItems) > 0 { +// res.TargetPath = "/" + path.Join(res.PathItems...) +// } +// return res, nil +// } +// +// if strings.HasPrefix(urlPath, "/api/") || urlPath == "/api" { +// return &TargetRequest{ +// IsCoreAPI: true, +// }, nil +// } +// +// return nil, nil +//} + +// Constants with indices of API endpoints portions. +// Request cluster scoped resource: +// - /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE +// | | | | +// APISIdx | | | +// GroupIDx | | +// VersionIDx ---+ | +// ClusterResourceIdx ---+ + +// +// Request namespaced resource: +// - /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE +// | | | +// NamespacesIdx --------+ | | +// NamespaceIdx --------------------+ | +// NamespacedResourceIdx----------------------+ +// +// Request CRD: +// - /apis/apiextensions.k8s.io/v1/customresourcedefinitions/RESOURCETYPE.GROUP +// | | | +// GroupIdx | | +// ClusterResourceIdx -------------+ | +// CRDNameIdx -----------------------------------------------+ + +//const ( +// APISIdx = 0 +// GroupIdx = 1 +// VersionIdx = 2 +// NamespacesIdx = 3 +// NamespaceIdx = 4 +// ClusterResourceIdx = 3 +// NamespacedResourceIdx = 5 +//) + +// RewriteAPIsPath rewrites GROUP and RESOURCETYPE in these API calls: +// - /apis/GROUP +// - /apis/GROUP/VERSION +// - /apis/GROUP/VERSION/RESOURCETYPE +// - /apis/GROUP/VERSION/RESOURCETYPE/NAME +// - /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE +// +// - /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE +// - /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME +// - /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE +//func RewriteAPIsPath(pathItems []string, rules *RewriteRules) (*TargetRequest, error) { +// if len(pathItems) == 0 { +// return nil, nil +// } +// +// res := &TargetRequest{ +// PathItems: make([]string, 0, len(pathItems)), +// } +// +// if len(pathItems) == 1 { +// if pathItems[APISIdx] == "apis" { +// // Do not rewrite URL, but rewrite response later. +// res.PathItems = append(res.PathItems, pathItems[APISIdx]) +// return res, nil +// } +// // The single path item should be "apis". +// return nil, nil +// } +// +// res.PathItems = append(res.PathItems, pathItems[APISIdx]) +// +// // Check if the GROUP portion match Rules. +// apiGroupName := "" +// apiGroupMatch := false +// group := pathItems[GroupIdx] +// for groupName, apiGroupRule := range rules.Rules { +// if apiGroupRule.GroupRule.Group == group { +// res.OrigGroup = group +// res.PathItems = append(res.PathItems, rules.RenamedGroup) +// apiGroupName = groupName +// apiGroupMatch = true +// break +// } +// } +// +// if !apiGroupMatch { +// return nil, nil +// } +// // Stop if GROUP is the last item in path. +// if len(pathItems) <= GroupIdx+1 { +// return res, nil +// } +// +// // Add VERSION portion. +// res.PathItems = append(res.PathItems, pathItems[VersionIdx]) +// // Stop if VERSION is the last item in path. +// if len(pathItems) <= VersionIdx+1 { +// return res, nil +// } +// +// // Check is namespaced resource is requested. +// resourceTypeIdx := ClusterResourceIdx +// if pathItems[NamespacesIdx] == "namespaces" { +// res.PathItems = append(res.PathItems, pathItems[NamespacesIdx]) +// res.PathItems = append(res.PathItems, pathItems[NamespaceIdx]) +// resourceTypeIdx = NamespacedResourceIdx +// } +// +// // Check if the RESOURCETYPE portion match Rules. +// resourceType := pathItems[resourceTypeIdx] +// resourceTypeMatched := true +// for _, rule := range rules.Rules[apiGroupName].ResourceRules { +// if rule.Plural == resourceType { +// res.OrigResourceType = resourceType +// res.PathItems = append(res.PathItems, rules.RenameResource(rule.Plural)) +// resourceTypeMatched = true +// break +// } +// } +// if !resourceTypeMatched { +// return nil, nil +// } +// // Return if RESOURCETYPE is the last item in path. +// if len(pathItems) == resourceTypeIdx+1 { +// return res, nil +// } +// +// // Copy remaining items: NAME and SUBRESOURCE. +// for i := resourceTypeIdx + 1; i < len(pathItems); i++ { +// res.PathItems = append(res.PathItems, pathItems[i]) +// } +// +// return res, nil +//} diff --git a/images/kube-api-proxy/pkg/rewriter/rbac.go b/images/kube-api-proxy/pkg/rewriter/rbac.go new file mode 100644 index 000000000..eacbdc42c --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/rbac.go @@ -0,0 +1,193 @@ +package rewriter + +import ( + "strings" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +const ( + ClusterRoleKind = "ClusterRole" + ClusterRoleListKind = "ClusterRoleList" + RoleKind = "Role" + RoleListKind = "RoleList" +) + +func RewriteClusterRoleOrList(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + if action == Rename { + return RewriteResourceOrList(obj, ClusterRoleListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "rules", func(item []byte) ([]byte, error) { + return renameRoleRule(rules, item) + }) + }) + } + return RewriteResourceOrList(obj, ClusterRoleListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "rules", func(item []byte) ([]byte, error) { + return restoreRoleRule(rules, item) + }) + }) +} + +func RewriteRoleOrList(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + if action == Rename { + return RewriteResourceOrList(obj, RoleListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "rules", func(item []byte) ([]byte, error) { + return renameRoleRule(rules, item) + }) + }) + } + return RewriteResourceOrList(obj, RoleListKind, func(singleObj []byte) ([]byte, error) { + return RewriteArray(singleObj, "rules", func(item []byte) ([]byte, error) { + return restoreRoleRule(rules, item) + }) + }) +} + +// renameRoleRule renames apiGroups and resources in a single rule. +// Rule examples: +// - apiGroups: +// - original.group.io +// resources: +// - '*' +// verbs: +// - '*' +// - apiGroups: +// - original.group.io +// resources: +// - someresources +// - someresources/finalizers +// - someresources/status +// - someresources/scale +// verbs: +// - watch +// - list +// - create +func renameRoleRule(rules *RewriteRules, obj []byte) ([]byte, error) { + var err error + + apiGroups := gjson.GetBytes(obj, "apiGroups").Array() + newGroups := []byte(`[]`) + shouldRename := false + for _, apiGroup := range apiGroups { + group := apiGroup.String() + if group == "*" { + shouldRename = true + } else if rules.HasGroup(group) { + group = rules.RenamedGroup + shouldRename = true + } + + newGroups, err = sjson.SetBytes(newGroups, "-1", group) + if err != nil { + return nil, err + } + } + + if !shouldRename { + return obj, nil + } + + resources := gjson.GetBytes(obj, "resources").Array() + newResources := []byte(`[]`) + for _, resource := range resources { + resourceType := resource.String() + if strings.Contains(resourceType, "/") { + resourceType, _, _ = strings.Cut(resource.String(), "/") + } + if resourceType != "*" { + _, resRule := rules.GroupResourceRules(resourceType) + if resRule != nil { + // TODO(future) make it work with suffix and subresource. + resourceType = rules.RenameResource(resource.String()) + } + } + + newResources, err = sjson.SetBytes(newResources, "-1", resourceType) + if err != nil { + return nil, err + } + } + + obj, err = sjson.SetRawBytes(obj, "apiGroups", newGroups) + if err != nil { + return nil, err + } + return sjson.SetRawBytes(obj, "resources", newResources) +} + +// restoreRoleRule restores apiGroups and resources in a single rule. +func restoreRoleRule(rules *RewriteRules, obj []byte) ([]byte, error) { + var err error + + apiGroups := gjson.GetBytes(obj, "apiGroups").Array() + newGroups := []byte(`[]`) + shouldRestore := false + shouldAddGroup := false + for _, apiGroup := range apiGroups { + group := apiGroup.String() + if group == "*" { + shouldRestore = true + } + if group == rules.RenamedGroup { + shouldRestore = true + shouldAddGroup = true + // Group will be restored later, do not add now. + continue + } + newGroups, err = sjson.SetBytes(newGroups, "-1", group) + if err != nil { + return nil, err + } + } + + if !shouldRestore { + return obj, nil + } + + // Loop over resources and detect group from rules. + + resources := gjson.GetBytes(obj, "resources").Array() + newResources := []byte(`[]`) + shouldRestore = false + groupToAdd := "" + for _, resource := range resources { + newResource := resource.String() + resourceType := resource.String() + //subresource := "" + if strings.Contains(resourceType, "/") { + resourceType, _, _ = strings.Cut(resourceType, "/") + } + if resourceType != "*" { + // Restore resourceType to get rules. + originalResourceType := rules.RestoreResource(resourceType) + groupRule, resRule := rules.GroupResourceRules(originalResourceType) + if groupRule != nil && resRule != nil { + shouldRestore = true + groupToAdd = groupRule.Group + // NOTE: Restore resource with subresource. + // TODO(future) make it work with suffixes. + newResource = rules.RestoreResource(resource.String()) + } + } + + newResources, err = sjson.SetBytes(newResources, "-1", newResource) + if err != nil { + return nil, err + } + } + + // Add restored group to apiGroups. + if shouldAddGroup && groupToAdd != "" { + newGroups, err = sjson.SetBytes(newGroups, "-1", groupToAdd) + if err != nil { + return nil, err + } + } + + obj, err = sjson.SetRawBytes(obj, "apiGroups", newGroups) + if err != nil { + return nil, err + } + return sjson.SetRawBytes(obj, "resources", newResources) +} diff --git a/images/kube-api-proxy/pkg/rewriter/rbac_test.go b/images/kube-api-proxy/pkg/rewriter/rbac_test.go new file mode 100644 index 000000000..4acbdbb41 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/rbac_test.go @@ -0,0 +1,147 @@ +package rewriter + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRenameRoleRule(t *testing.T) { + + tests := []struct { + name string + rule string + expect string + }{ + { + "group and resources", + `{"apiGroups":["original.group.io"], +"resources": ["someresources","someresources/finalizers","someresources/status"], +"verbs": ["watch", "list", "create"] +}`, + `{"apiGroups":["prefixed.resources.group.io"], +"resources": ["prefixedsomeresources","prefixedsomeresources/finalizers","prefixedsomeresources/status"], +"verbs": ["watch", "list", "create"] +}`, + }, + { + "only resources", + `{"apiGroups":["*"], +"resources": ["someresources","someresources/finalizers","someresources/status"], +"verbs": ["watch", "list", "create"] +}`, + `{"apiGroups":["*"], +"resources": ["prefixedsomeresources","prefixedsomeresources/finalizers","prefixedsomeresources/status"], +"verbs": ["watch", "list", "create"] +}`, + }, + { + "only group", + `{"apiGroups":["original.group.io"], +"resources": ["*"], +"verbs": ["watch", "list", "create"] +}`, + `{"apiGroups":["prefixed.resources.group.io"], +"resources": ["*"], +"verbs": ["watch", "list", "create"] +}`, + }, + { + "allow all", + `{"apiGroups":["*"], "resources":["*"], "verbs":["*"]}`, + `{"apiGroups":["*"], "resources":["*"], "verbs":["*"]}`, + }, + { + "unknown group", + `{"apiGroups":["unknown.group.io"], "resources":["someresources"], "verbs":["*"]}`, + `{"apiGroups":["unknown.group.io"], "resources":["someresources"], "verbs":["*"]}`, + }, + { + "core resource", + `{"apiGroups":[""], "resources":["pods"], "verbs":["create"]}`, + `{"apiGroups":[""], "resources":["pods"], "verbs":["create"]}`, + }, + } + + rwr := createTestRewriter() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resBytes, err := renameRoleRule(rwr.Rules, []byte(tt.rule)) + require.NoError(t, err, "should rename rule") + + actual := string(resBytes) + require.Equal(t, tt.expect, actual) + }) + } +} + +func TestRestoreRoleRule(t *testing.T) { + tests := []struct { + name string + rule string + expect string + }{ + { + "group and resources", + `{"apiGroups":["prefixed.resources.group.io"], +"resources": ["prefixedsomeresources","prefixedsomeresources/finalizers","prefixedsomeresources/status"], +"verbs": ["watch", "list", "create"] +}`, + `{"apiGroups":["original.group.io"], +"resources": ["someresources","someresources/finalizers","someresources/status"], +"verbs": ["watch", "list", "create"] +}`, + }, + { + "only resources", + `{"apiGroups":["*"], +"resources": ["prefixedsomeresources","prefixedsomeresources/finalizers","prefixedsomeresources/status"], +"verbs": ["watch", "list", "create"] +}`, + `{"apiGroups":["*"], +"resources": ["someresources","someresources/finalizers","someresources/status"], +"verbs": ["watch", "list", "create"] +}`, + }, + // Impossible to restore with current rules. + // { + // "only group", + // `{"apiGroups":["prefixed.resources.group.io"], + //"resources": ["*"], + //"verbs": ["watch", "list", "create"] + //}`, + // `{"apiGroups":["original.group.io"], + //"resources": ["*"], + //"verbs": ["watch", "list", "create"] + //}`, + // }, + { + "allow all", + `{"apiGroups":["*"], "resources":["*"], "verbs":["*"]}`, + `{"apiGroups":["*"], "resources":["*"], "verbs":["*"]}`, + }, + { + "unknown group", + `{"apiGroups":["unknown.group.io"], "resources":["someresources"], "verbs":["*"]}`, + `{"apiGroups":["unknown.group.io"], "resources":["someresources"], "verbs":["*"]}`, + }, + { + "core resource", + `{"apiGroups":[""], "resources":["pods","configmaps"], "verbs":["create"]}`, + `{"apiGroups":[""], "resources":["pods","configmaps"], "verbs":["create"]}`, + }, + } + + rwr := createTestRewriter() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resBytes, err := restoreRoleRule(rwr.Rules, []byte(tt.rule)) + require.NoError(t, err, "should rename rule") + + actual := string(resBytes) + require.Equal(t, tt.expect, actual) + }) + } +} diff --git a/images/kube-api-proxy/pkg/rewriter/resource.go b/images/kube-api-proxy/pkg/rewriter/resource.go new file mode 100644 index 000000000..e89b8b1b8 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/resource.go @@ -0,0 +1,343 @@ +package rewriter + +import ( + "strings" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +func RewriteCustomResourceOrList(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + kind := gjson.GetBytes(obj, "kind").String() + if action == Restore { + kind = rules.RestoreKind(kind) + } + origGroupName, origResName, isList := rules.ResourceByKind(kind) + if origGroupName == "" && origResName == "" { + // Return as-is if kind is not in rules. + return obj, nil + } + if isList { + if action == Restore { + return RestoreResourcesList(rules, obj, origGroupName) + } + + return RenameResourcesList(rules, obj) + } + + // Responses of GET, LIST, DELETE requests. + // AdmissionReview requests from API Server. + if action == Restore { + return RestoreResource(rules, obj, origGroupName) + } + // CREATE, UPDATE, PATCH requests. + // TODO need to implement for + return RenameResource(rules, obj) +} + +func RenameResourcesList(rules *RewriteRules, obj []byte) ([]byte, error) { + obj, err := RenameAPIVersionAndKind(rules, obj) + if err != nil { + return nil, err + } + + // Rewrite apiVersion and kind in each item. + items := gjson.GetBytes(obj, "items").Array() + rwrItems := []byte(`[]`) + for _, item := range items { + rwrItem, err := RenameResource(rules, []byte(item.Raw)) + if err != nil { + return nil, err + } + rwrItems, err = sjson.SetRawBytes(rwrItems, "-1", rwrItem) + } + + obj, err = sjson.SetRawBytes(obj, "items", rwrItems) + if err != nil { + return nil, err + } + + return obj, nil +} + +func RestoreResourcesList(rules *RewriteRules, obj []byte, origGroupName string) ([]byte, error) { + obj, err := RestoreAPIVersionAndKind(rules, obj, origGroupName) + if err != nil { + return nil, err + } + + // Rewrite apiVersion and kind in each item. + items := gjson.GetBytes(obj, "items").Array() + rwrItems := []byte(`[]`) + for _, item := range items { + rwrItem, err := RestoreResource(rules, []byte(item.Raw), origGroupName) + if err != nil { + return nil, err + } + rwrItems, err = sjson.SetRawBytes(rwrItems, "-1", rwrItem) + } + + obj, err = sjson.SetRawBytes(obj, "items", rwrItems) + if err != nil { + return nil, err + } + + return obj, nil +} + +func RenameResource(rules *RewriteRules, obj []byte) ([]byte, error) { + obj, err := RenameAPIVersionAndKind(rules, obj) + if err != nil { + return nil, err + } + + // Rewrite apiVersion in each managedFields. + obj, err = RenameManagedFields(rules, obj) + if err != nil { + return nil, err + } + + return RenameOwnerReferences(rules, obj) +} + +func RestoreResource(rules *RewriteRules, obj []byte, origGroupName string) ([]byte, error) { + obj, err := RestoreAPIVersionAndKind(rules, obj, origGroupName) + if err != nil { + return nil, err + } + + // Rewrite apiVersion in each managedFields. + obj, err = RestoreManagedFields(rules, obj, origGroupName) + if err != nil { + return nil, err + } + + return RestoreOwnerReferences(rules, obj, origGroupName) +} + +func RenameAPIVersionAndKind(rules *RewriteRules, obj []byte) ([]byte, error) { + apiVersion := gjson.GetBytes(obj, "apiVersion").String() + obj, err := sjson.SetBytes(obj, "apiVersion", rules.RenameApiVersion(apiVersion)) + if err != nil { + return nil, err + } + + kind := gjson.GetBytes(obj, "kind").String() + return sjson.SetBytes(obj, "kind", rules.RenameKind(kind)) +} + +func RestoreAPIVersionAndKind(rules *RewriteRules, obj []byte, origGroupName string) ([]byte, error) { + apiVersion := gjson.GetBytes(obj, "apiVersion").String() + apiVersion = rules.RestoreApiVersion(apiVersion, origGroupName) + obj, err := sjson.SetBytes(obj, "apiVersion", apiVersion) + if err != nil { + return nil, err + } + + kind := gjson.GetBytes(obj, "kind").String() + return sjson.SetBytes(obj, "kind", rules.RestoreKind(kind)) +} + +func RewriteOwnerReferences(rules *RewriteRules, obj []byte, action Action) ([]byte, error) { + ownerRefs := gjson.GetBytes(obj, "metadata.ownerReferences").Array() + if len(ownerRefs) == 0 { + return obj, nil + } + + rwrOwnerRefs := []byte(`[]`) + rewritten := false + for _, ownerRef := range ownerRefs { + kind := ownerRef.Get("kind").String() + if action == Restore { + kind = rules.RestoreKind(kind) + } + // Find if kind should be rewritten. + origGroup, origResource, _ := rules.ResourceByKind(kind) + if origGroup == "" && origResource == "" { + // There is no rewrite rule for kind, append ownerRef as is. + var err error + rwrOwnerRefs, err = sjson.SetRawBytes(rwrOwnerRefs, "-1", []byte(ownerRef.Raw)) + if err != nil { + return nil, err + } + continue + } + if action == Rename { + kind = rules.RenameKind(kind) + } + + rwrOwnerRef := []byte(ownerRef.Raw) + + rwrOwnerRef, err := sjson.SetBytes(rwrOwnerRef, "kind", kind) + if err != nil { + return nil, err + } + + apiVersion := ownerRef.Get("apiVersion").String() + if action == Restore { + apiVersion = rules.RestoreApiVersion(apiVersion, origGroup) + } + if action == Rename { + apiVersion = rules.RenameApiVersion(apiVersion) + } + rwrOwnerRef, err = sjson.SetBytes(rwrOwnerRef, "apiVersion", apiVersion) + if err != nil { + return nil, err + } + + rwrOwnerRefs, err = sjson.SetRawBytes(rwrOwnerRefs, "-1", rwrOwnerRef) + rewritten = true + } + if rewritten { + return sjson.SetRawBytes(obj, "metadata.ownerReferences", rwrOwnerRefs) + } + + return obj, nil +} + +// RenameOwnerReferences renames kind and apiVersion to send request to server. +func RenameOwnerReferences(rules *RewriteRules, obj []byte) ([]byte, error) { + ownerRefs := gjson.GetBytes(obj, "metadata.ownerReferences").Array() + if len(ownerRefs) == 0 { + return obj, nil + } + + rwrOwnerRefs := []byte(`[]`) + var err error + for _, ownerRef := range ownerRefs { + apiVersion := ownerRef.Get("apiVersion").String() + kind := ownerRef.Get("kind").String() + + rwrOwnerRef := []byte(ownerRef.Raw) + + _, resRule := rules.KindRules(apiVersion, kind) + if resRule != nil { + // Rename apiVersion and kind if resource has renaming rules. + rwrOwnerRef, err = sjson.SetBytes(rwrOwnerRef, "kind", rules.RenameKind(kind)) + if err != nil { + return nil, err + } + + rwrOwnerRef, err = sjson.SetBytes(rwrOwnerRef, "apiVersion", rules.RenameApiVersion(apiVersion)) + if err != nil { + return nil, err + } + } + + rwrOwnerRefs, err = sjson.SetRawBytes(rwrOwnerRefs, "-1", rwrOwnerRef) + if err != nil { + return nil, err + } + } + return sjson.SetRawBytes(obj, "metadata.ownerReferences", rwrOwnerRefs) +} + +// RestoreOwnerReferences restores kind and apiVersion to consume by the client. +// There are no checks if resource should be restored. This should be determined by the caller. +// +// Example response from the server: +// apiVersion: x.virtualization.deckhouse.io/v1 +// kind: VirtualMachineInstance +// metadata: +// +// name: ... +// namespace: .. +// ownerReferences: +// - apiVersion: x.virtualization.deckhouse.io/v1 <--- restore apiVersion +// blockOwnerDeletion: true +// controller: true +// kind: VirtualMachine <--- restore kind +// name: cloud-alpine +// uid: 4c74c3ff-2199-4f20-a71c-3b0e5fb505ca +func RestoreOwnerReferences(rules *RewriteRules, obj []byte, groupName string) ([]byte, error) { + ownerRefs := gjson.GetBytes(obj, "metadata.ownerReferences").Array() + if len(ownerRefs) == 0 { + return obj, nil + } + rOwnerRefs := []byte(`[]`) + restored := false + for _, ownerRef := range ownerRefs { + apiVersion := ownerRef.Get("apiVersion").String() + rOwnerRef := []byte(ownerRef.Raw) + var err error + if strings.HasPrefix(apiVersion, rules.RenamedGroup) { + rOwnerRef, err = sjson.SetBytes([]byte(ownerRef.Raw), "apiVersion", rules.RestoreApiVersion(apiVersion, groupName)) + if err != nil { + return nil, err + } + kind := gjson.GetBytes(rOwnerRef, "kind").String() + rOwnerRef, err = sjson.SetBytes(rOwnerRef, "kind", rules.RestoreKind(kind)) + if err != nil { + return nil, err + } + restored = true + } + rOwnerRefs, err = sjson.SetRawBytes(rOwnerRefs, "-1", rOwnerRef) + } + if restored { + return sjson.SetRawBytes(obj, "metadata.ownerReferences", rOwnerRefs) + } + return obj, nil +} + +// RestoreManagedFields restores apiVersion in managedFields items. +// +// Example response from the server: +// +// "metadata": { +// "managedFields":[ +// { "apiVersion":"x.virtualization.deckhouse.io/v1", "fieldsType":"FieldsV1", "fieldsV1":{ ... }}, "manager": "Go-http-client", ...}, +// { "apiVersion":"x.virtualization.deckhouse.io/v1", "fieldsType":"FieldsV1", "fieldsV1":{ ... }}, "manager": "kubectl-edit", ...} +// ], +func RestoreManagedFields(rules *RewriteRules, obj []byte, origGroupName string) ([]byte, error) { + mgFields := gjson.GetBytes(obj, "metadata.managedFields") + if !mgFields.Exists() || len(mgFields.Array()) == 0 { + return obj, nil + } + + newFields := []byte(`[]`) + for _, mgField := range mgFields.Array() { + apiVersion := mgField.Get("apiVersion").String() + restoredAPIVersion := rules.RestoreApiVersion(apiVersion, origGroupName) + newField, err := sjson.SetBytes([]byte(mgField.Raw), "apiVersion", restoredAPIVersion) + if err != nil { + return nil, err + } + newFields, err = sjson.SetRawBytes(newFields, "-1", newField) + if err != nil { + return nil, err + } + } + return sjson.SetRawBytes(obj, "metadata.managedFields", newFields) +} + +// RenameManagedFields renames apiVersion in managedFields items. +// +// Example request from the client: +// +// "metadata": { +// "managedFields":[ +// { "apiVersion":"kubevirt.io/v1", "fieldsType":"FieldsV1", "fieldsV1":{ ... }}, "manager": "Go-http-client", ...}, +// { "apiVersion":"kubevirt.io/v1", "fieldsType":"FieldsV1", "fieldsV1":{ ... }}, "manager": "kubectl-edit", ...} +// ], +func RenameManagedFields(rules *RewriteRules, obj []byte) ([]byte, error) { + mgFields := gjson.GetBytes(obj, "metadata.managedFields") + if !mgFields.Exists() || len(mgFields.Array()) == 0 { + return obj, nil + } + + newFields := []byte(`[]`) + for _, mgField := range mgFields.Array() { + apiVersion := mgField.Get("apiVersion").String() + renamedAPIVersion := rules.RenameApiVersion(apiVersion) + newField, err := sjson.SetBytes([]byte(mgField.Raw), "apiVersion", renamedAPIVersion) + if err != nil { + return nil, err + } + newFields, err = sjson.SetRawBytes(newFields, "-1", newField) + if err != nil { + return nil, err + } + } + return sjson.SetRawBytes(obj, "metadata.managedFields", newFields) +} diff --git a/images/kube-api-proxy/pkg/rewriter/rule_rewriter.go b/images/kube-api-proxy/pkg/rewriter/rule_rewriter.go new file mode 100644 index 000000000..06d9e9414 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/rule_rewriter.go @@ -0,0 +1,208 @@ +package rewriter + +import ( + "regexp" + "strings" + + "github.com/tidwall/gjson" +) + +type RuleBasedRewriter struct { + Rules *RewriteRules +} + +type Action string + +const ( + // Restore is an action to restore resources to original. + Restore Action = "restore" + // Rename is an action to rename original resources. + Rename Action = "rename" +) + +// RewriteAPIEndpoint renames group and resource in /apis/* endpoints. +// It assumes that ep contains original group and resourceType. +// Restoring of path is not implemented. +func (rw *RuleBasedRewriter) RewriteAPIEndpoint(ep *APIEndpoint) *APIEndpoint { + // Leave paths /, /api, /api/*, and unknown paths as is. + if ep.IsRoot || ep.IsCore || ep.IsUnknown { + return nil + } + + // Rename CRD name resourcetype.group for resources with rules. + if ep.IsCRD { + // No endpoint rewrite for CRD list. + if ep.CRDGroup == "" && ep.CRDResourceType == "" { + if strings.Contains(ep.RawQuery, "metadata.name") { + // Rewrite name in field selector if any. + newQuery := rw.rewriteFieldSelector(ep.RawQuery) + if newQuery != "" { + res := ep.Clone() + res.RawQuery = newQuery + return res + } + } + return nil + } + + // Check if resource has rules + _, resourceRule := rw.Rules.ResourceRules(ep.CRDGroup, ep.CRDResourceType) + if resourceRule == nil { + // No rewrite for CRD without rules. + return nil + } + // Rewrite CRD name. + res := ep.Clone() + res.CRDGroup = rw.Rules.RenamedGroup + res.CRDResourceType = rw.Rules.RenameResource(res.CRDResourceType) + res.Name = res.CRDResourceType + "." + res.CRDGroup + return res + } + + // Rename group and resource for CR requests. + newGroup := "" + if ep.Group != "" { + groupRule := rw.Rules.GroupRule(ep.Group) + if groupRule == nil { + // No rewrite for group without rules. + return nil + } + newGroup = rw.Rules.RenamedGroup + } + + newResource := "" + if ep.ResourceType != "" { + _, resRule := rw.Rules.ResourceRules(ep.Group, ep.ResourceType) + if resRule != nil { + newResource = rw.Rules.RenameResource(ep.ResourceType) + } + } + + // Return rewritten endpoint if group or resource are changed. + if newGroup != "" || newResource != "" { + res := ep.Clone() + if newGroup != "" { + res.Group = newGroup + } + if newResource != "" { + res.ResourceType = newResource + } + + return res + } + + return nil +} + +var metadataNameRe = regexp.MustCompile(`metadata.name\%3D([a-z0-9-]+)((\.[a-z0-9-]+)*)`) + +// rewriteFieldSelector rewrites value for metadata.name in fieldSelector of CRDs listing. +// Example request: +// https://APISERVER/apis/apiextensions.k8s.io/v1/customresourcedefinitions?fieldSelector=metadata.name%3Dresources.original.group.io&... +func (rw *RuleBasedRewriter) rewriteFieldSelector(rawQuery string) string { + matches := metadataNameRe.FindStringSubmatch(rawQuery) + if matches == nil { + return "" + } + + resourceType := matches[1] + group := matches[2] + group = strings.TrimPrefix(group, ".") + + _, resRule := rw.Rules.ResourceRules(group, resourceType) + if resRule == nil { + return "" + } + + group = rw.Rules.RenamedGroup + resourceType = rw.Rules.RenameResource(resourceType) + + newSelector := `metadata.name%3D` + resourceType + "." + group + + return metadataNameRe.ReplaceAllString(rawQuery, newSelector) +} + +// RewriteJSONPayload does rewrite based on kind. +func (rw *RuleBasedRewriter) RewriteJSONPayload(targetReq *TargetRequest, obj []byte, action Action) ([]byte, error) { + // Detect Kind + kind := gjson.GetBytes(obj, "kind").String() + + var rwrBytes []byte + var err error + + //// Handle core resources: rewrite only for specific kind. + //if targetReq.IsCore() { + // pass := true + // switch kind { + // case "APIGroupList": + // case "APIGroup": + // case "APIResourceList": + // default: + // pass = shouldPassCoreResource(kind) + // } + // if pass { + // return obj, nil + // } + //} + + switch kind { + case "APIGroupList": + rwrBytes, err = RewriteAPIGroupList(rw.Rules, obj) + + case "APIGroup": + rwrBytes, err = RewriteAPIGroup(rw.Rules, obj, targetReq.OrigGroup()) + + case "APIResourceList": + rwrBytes, err = RewriteAPIResourceList(rw.Rules, obj, targetReq.OrigGroup()) + + case "AdmissionReview": + rwrBytes, err = RewriteAdmissionReview(rw.Rules, obj, targetReq.OrigGroup()) + + case CRDKind, CRDListKind: + rwrBytes, err = RewriteCRDOrList(rw.Rules, obj, action) + + case MutatingWebhookConfigurationKind, + MutatingWebhookConfigurationListKind: + rwrBytes, err = RewriteMutatingOrList(rw.Rules, obj, action) + + case ValidatingWebhookConfigurationKind, + ValidatingWebhookConfigurationListKind: + rwrBytes, err = RewriteValidatingOrList(rw.Rules, obj, action) + + case ClusterRoleKind, ClusterRoleListKind: + rwrBytes, err = RewriteClusterRoleOrList(rw.Rules, obj, action) + + case RoleKind, RoleListKind: + rwrBytes, err = RewriteRoleOrList(rw.Rules, obj, action) + + default: + if targetReq.IsCore() { + rwrBytes, err = RewriteOwnerReferences(rw.Rules, obj, action) + } else { + rwrBytes, err = RewriteCustomResourceOrList(rw.Rules, obj, action) + } + } + + // Return obj bytes as-is in case of the error. + if err != nil { + return obj, err + } + + return rwrBytes, nil +} + +// RewritePatch rewrites patches for some known objects. +// Only rename action is required for patches. +func (rw *RuleBasedRewriter) RewritePatch(targetReq *TargetRequest, obj []byte) ([]byte, error) { + if targetReq.IsCRD() { + // Check if CRD is known. + _, resRule := rw.Rules.ResourceRules(targetReq.OrigGroup(), targetReq.OrigResourceType()) + if resRule == nil { + return obj, nil + } + + return RenameCRDPatch(rw.Rules, resRule, obj) + } + + return obj, nil +} diff --git a/images/kube-api-proxy/pkg/rewriter/rule_rewriter_test.go b/images/kube-api-proxy/pkg/rewriter/rule_rewriter_test.go new file mode 100644 index 000000000..846706791 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/rule_rewriter_test.go @@ -0,0 +1,133 @@ +package rewriter + +import ( + "net/url" + "testing" + + "github.com/stretchr/testify/require" +) + +func createTestRewriter() *RuleBasedRewriter { + apiGroupRules := map[string]APIGroupRule{ + "original.group.io": { + GroupRule: GroupRule{ + Group: "original.group.io", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + }, + ResourceRules: map[string]ResourceRule{ + "someresources": { + Kind: "SomeResource", + ListKind: "SomeResourceList", + Plural: "someresources", + Singular: "someresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + Categories: []string{"all"}, + ShortNames: []string{"sr", "srs"}, + }, + "anotherresources": { + Kind: "AnotherResource", + ListKind: "AnotherResourceList", + Plural: "anotherresources", + Singular: "anotherresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + ShortNames: []string{"ar"}, + }, + }, + }, + "other.group.io": { + GroupRule: GroupRule{ + Group: "original.group.io", + Versions: []string{"v2alpha3"}, + PreferredVersion: "v2alpha3", + }, + ResourceRules: map[string]ResourceRule{ + "otherresources": { + Kind: "OtherResource", + ListKind: "OtherResourceList", + Plural: "otherresources", + Singular: "otherresource", + Versions: []string{"v1", "v1alpha1"}, + PreferredVersion: "v1", + ShortNames: []string{"or"}, + }, + }, + }, + } + + rules := &RewriteRules{ + KindPrefix: "Prefixed", // KV + ResourceTypePrefix: "prefixed", // kv + ShortNamePrefix: "p", + Categories: []string{"prefixed"}, + RenamedGroup: "prefixed.resources.group.io", + Rules: apiGroupRules, + } + + return &RuleBasedRewriter{ + Rules: rules, + } +} + +func TestRewriteAPIEndpoint(t *testing.T) { + tests := []struct { + name string + path string + expect string + }{ + { + "rewritable group", + "/apis/original.group.io", + "/apis/prefixed.resources.group.io", + }, + { + "rewritable group and version", + "/apis/original.group.io/v1", + "/apis/prefixed.resources.group.io/v1", + }, + { + "rewritable resource list", + "/apis/original.group.io/v1/someresources", + "/apis/prefixed.resources.group.io/v1/prefixedsomeresources", + }, + { + "rewritable resource by name", + "/apis/original.group.io/v1/someresources/srname", + "/apis/prefixed.resources.group.io/v1/prefixedsomeresources/srname", + }, + { + "rewritable resource status", + "/apis/original.group.io/v1/someresources/srname/status", + "/apis/prefixed.resources.group.io/v1/prefixedsomeresources/srname/status", + }, + { + "rewritable CRD", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/someresources.original.group.io", + "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/prefixedsomeresources.prefixed.resources.group.io", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u, err := url.Parse(tt.path) + require.NoError(t, err, "should parse path '%s'", tt.path) + + ep := ParseAPIEndpoint(u) + + rwr := createTestRewriter() + + newEp := rwr.RewriteAPIEndpoint(ep) + + if tt.expect == "" { + require.Nil(t, newEp, "should not rewrite path '%s', got %+v", tt.path, newEp) + } + + require.NotNil(t, newEp, "should rewrite path '%s', got nil originEndpoint") + + require.Equal(t, tt.expect, newEp.Path(), "expect rewrite for path '%s' to be '%s', got '%s'", tt.path, tt.expect, ep.Path()) + }) + } + +} diff --git a/images/kube-api-proxy/pkg/rewriter/rules.go b/images/kube-api-proxy/pkg/rewriter/rules.go new file mode 100644 index 000000000..a8fc1ec60 --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/rules.go @@ -0,0 +1,210 @@ +package rewriter + +import "strings" + +type RewriteRules struct { + KindPrefix string `json:"kindPrefix"` + ResourceTypePrefix string `json:"resourceTypePrefix"` + ShortNamePrefix string `json:"shortNamePrefix"` + Categories []string `json:"categories"` + RenamedGroup string `json:"renamedGroup"` + Rules map[string]APIGroupRule `json:"rules"` + Webhooks map[string]WebhookRule `json:"webhooks"` +} + +type APIGroupRule struct { + GroupRule GroupRule `json:"groupRule"` + ResourceRules map[string]ResourceRule `json:"resourceRules"` +} + +type GroupRule struct { + Group string `json:"group"` + Versions []string `json:"versions"` + PreferredVersion string `json:"preferredVersion"` +} + +type ResourceRule struct { + Kind string `json:"kind"` + ListKind string `json:"listKind"` + Plural string `json:"plural"` + Singular string `json:"singular"` + ShortNames []string `json:"shortNames"` + Categories []string `json:"categories"` + Versions []string `json:"versions"` + PreferredVersion string `json:"preferredVersion"` +} + +type WebhookRule struct { + Path string `json:"path"` + Group string `json:"group"` + Resource string `json:"resource"` +} + +// GetAPIGroupList returns an array of groups in format applicable to use in APIGroupList: +// +// { +// name +// versions: [ { groupVersion, version } ... ] +// preferredVersion: { groupVersion, version } +// } +func (rr *RewriteRules) GetAPIGroupList() []interface{} { + groups := make([]interface{}, 0) + + for _, rGroup := range rr.Rules { + group := map[string]interface{}{ + "name": rGroup.GroupRule.Group, + "preferredVersion": map[string]interface{}{ + "groupVersion": rGroup.GroupRule.Group + "/" + rGroup.GroupRule.PreferredVersion, + "version": rGroup.GroupRule.PreferredVersion, + }, + } + versions := make([]interface{}, 0) + for _, ver := range rGroup.GroupRule.Versions { + versions = append(versions, map[string]interface{}{ + "groupVersion": rGroup.GroupRule.Group + "/" + ver, + "version": ver, + }) + } + group["versions"] = versions + groups = append(groups, group) + } + + return groups +} + +func (rr *RewriteRules) ResourceByKind(kind string) (string, string, bool) { + for groupName, group := range rr.Rules { + for resName, res := range group.ResourceRules { + if res.Kind == kind { + return groupName, resName, false + } + if res.ListKind == kind { + return groupName, resName, true + } + } + } + return "", "", false +} + +func (rr *RewriteRules) WebhookRule(path string) *WebhookRule { + if webhookRule, ok := rr.Webhooks[path]; ok { + return &webhookRule + } + return nil +} + +func (rr *RewriteRules) HasGroup(group string) bool { + _, ok := rr.Rules[group] + return ok +} + +func (rr *RewriteRules) GroupRule(group string) *GroupRule { + if groupRule, ok := rr.Rules[group]; ok { + return &groupRule.GroupRule + } + return nil +} + +// KindRules returns rule for group and resource by apiGroup and kind. +// apiGroup may be a group or a group with version. +func (rr *RewriteRules) KindRules(apiGroup, kind string) (*GroupRule, *ResourceRule) { + group, _, _ := strings.Cut(apiGroup, "/") + groupRule, ok := rr.Rules[group] + if !ok { + return nil, nil + } + + for _, resRule := range groupRule.ResourceRules { + if resRule.Kind == kind { + return &groupRule.GroupRule, &resRule + } + if resRule.ListKind == kind { + return &groupRule.GroupRule, &resRule + } + } + return nil, nil +} + +func (rr *RewriteRules) ResourceRules(group, resource string) (*GroupRule, *ResourceRule) { + groupRule, ok := rr.Rules[group] + if !ok { + return nil, nil + } + resourceRule, ok := rr.Rules[group].ResourceRules[resource] + if !ok { + return nil, nil + } + return &groupRule.GroupRule, &resourceRule +} + +func (rr *RewriteRules) GroupResourceRules(resourceType string) (*GroupRule, *ResourceRule) { + for _, group := range rr.Rules { + for _, res := range group.ResourceRules { + if res.Plural == resourceType { + return &group.GroupRule, &res + } + } + } + return nil, nil +} + +func (rr *RewriteRules) RenameResource(resource string) string { + return rr.ResourceTypePrefix + resource +} + +func (rr *RewriteRules) RenameKind(kind string) string { + return rr.KindPrefix + kind +} + +func (rr *RewriteRules) RestoreResource(resource string) string { + return strings.TrimPrefix(resource, rr.ResourceTypePrefix) +} + +func (rr *RewriteRules) RestoreKind(kind string) string { + return strings.TrimPrefix(kind, rr.KindPrefix) +} + +func (rr *RewriteRules) RestoreApiVersion(apiVersion string, group string) string { + // Replace group, keep version. + slashVersion := strings.TrimPrefix(apiVersion, rr.RenamedGroup) + return group + slashVersion +} + +func (rr *RewriteRules) RenameApiVersion(apiVersion string) string { + // Replace group, keep version. + apiVerParts := strings.Split(apiVersion, "/") + if len(apiVerParts) != 2 { + return apiVersion + } + return rr.RenamedGroup + "/" + apiVerParts[1] +} + +func (rr *RewriteRules) RenameCategories(categories []string) []string { + if len(categories) == 0 { + return []string{} + } + return rr.Categories +} + +func (rr *RewriteRules) RestoreCategories(resourceRule *ResourceRule) []string { + if resourceRule == nil { + return []string{} + } + return resourceRule.Categories +} + +func (rr *RewriteRules) RenameShortNames(shortNames []string) []string { + newNames := make([]string, 0, len(shortNames)) + for _, shortName := range shortNames { + newNames = append(newNames, rr.ShortNamePrefix+shortName) + } + return newNames +} + +func (rr *RewriteRules) RestoreShortNames(shortNames []string) []string { + newNames := make([]string, 0, len(shortNames)) + for _, shortName := range shortNames { + newNames = append(newNames, strings.TrimPrefix(shortName, rr.ShortNamePrefix)) + } + return newNames +} diff --git a/images/kube-api-proxy/pkg/rewriter/target_request.go b/images/kube-api-proxy/pkg/rewriter/target_request.go new file mode 100644 index 000000000..4a7606f5f --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/target_request.go @@ -0,0 +1,278 @@ +package rewriter + +import ( + "net/http" +) + +type TargetRequest struct { + originEndpoint *APIEndpoint + targetEndpoint *APIEndpoint + + webhookRule *WebhookRule +} + +func NewTargetRequest(rwr *RuleBasedRewriter, req *http.Request) *TargetRequest { + if req == nil || req.URL == nil { + return nil + } + + // Is it a request to the webhook? + webhookRule := rwr.Rules.WebhookRule(req.URL.Path) + if webhookRule != nil { + return &TargetRequest{ + webhookRule: webhookRule, + } + } + + apiEndpoint := ParseAPIEndpoint(req.URL) + if apiEndpoint == nil { + return nil + } + + // rewrite path if needed + targetEndpoint := rwr.RewriteAPIEndpoint(apiEndpoint) + + return &TargetRequest{ + originEndpoint: apiEndpoint, + targetEndpoint: targetEndpoint, + } +} + +// Path return possibly rewritten path for target endpoint. +func (tr *TargetRequest) Path() string { + if tr.targetEndpoint != nil { + return tr.targetEndpoint.Path() + } + if tr.originEndpoint != nil { + return tr.originEndpoint.Path() + } + if tr.webhookRule != nil { + return tr.webhookRule.Path + } + + return "" +} + +func (tr *TargetRequest) IsCore() bool { + if tr.originEndpoint != nil { + return tr.originEndpoint.IsCore + } + return false +} + +func (tr *TargetRequest) IsCRD() bool { + if tr.originEndpoint != nil { + return tr.originEndpoint.IsCRD + } + return false +} + +func (tr *TargetRequest) IsWatch() bool { + if tr.originEndpoint != nil { + return tr.originEndpoint.IsWatch + } + return false +} + +func (tr *TargetRequest) OrigGroup() string { + if tr.IsCRD() { + return tr.originEndpoint.CRDGroup + } + if tr.originEndpoint != nil { + return tr.originEndpoint.Group + } + if tr.webhookRule != nil { + return tr.webhookRule.Group + } + return "" +} + +func (tr *TargetRequest) OrigResourceType() string { + if tr.IsCRD() { + return tr.originEndpoint.CRDResourceType + } + if tr.originEndpoint != nil { + return tr.originEndpoint.ResourceType + } + if tr.webhookRule != nil { + return tr.webhookRule.Resource + } + return "" +} + +func (tr *TargetRequest) RawQuery() string { + if tr.targetEndpoint != nil { + return tr.targetEndpoint.RawQuery + } + if tr.originEndpoint != nil { + return tr.originEndpoint.RawQuery + } + return "" +} + +// ShouldRewriteRequest returns true if incoming payload should +// be rewritten. +func (tr *TargetRequest) ShouldRewriteRequest() bool { + // Consider known webhook should be rewritten. Unknown paths will be passed as-is. + if tr.webhookRule != nil { + return true + } + + if tr.originEndpoint != nil { + if tr.originEndpoint.IsRoot || tr.originEndpoint.IsUnknown { + return false + } + + if tr.targetEndpoint == nil { + // Pass resources without rules as is, except some special types. + + if tr.originEndpoint.IsCore { + switch tr.originEndpoint.ResourceType { + case "pods": + return true + } + } + + switch tr.originEndpoint.ResourceType { + case "mutatingwebhookconfigurations", + "validatingwebhookconfigurations", + "clusterroles", + "roles": + return true + } + + // Rewrite request body when creating CRD. + if tr.originEndpoint.ResourceType == "customresourcedefinitions" && tr.originEndpoint.Name == "" { + return true + } + + // Should not rewrite request if path is not rewritten. + return false + } + } + + // Payload should be inspected to decide if rewrite is required. + return true +} + +// ShouldRewriteResponse return true if response rewrite is needed. +// Response may be passed as is if false. +func (tr *TargetRequest) ShouldRewriteResponse() bool { + // If there is webhook rule, response should be rewritten. + if tr.webhookRule != nil { + return true + } + + if tr.originEndpoint == nil { + return false + } + + if tr.originEndpoint.IsRoot || tr.originEndpoint.IsUnknown { + return false + } + + // Some core resources should be rewritten. + if tr.originEndpoint.IsCore { + switch tr.originEndpoint.ResourceType { + case "pods": + return true + // pods should be rewritten + } + return false + } + + if tr.originEndpoint.IsCRD { + // Rewrite CRD List. + if tr.originEndpoint.Name == "" { + return true + } + // Rewrite CRD if group and resource was rewritten. + if tr.originEndpoint.Name != "" && tr.targetEndpoint != nil { + return true + } + return false + } + + // Rewrite if path was rewritten for known resource. + if tr.targetEndpoint != nil { + return true + } + + // Rewrite response from /apis discovery. + if tr.originEndpoint.Group == "" { + return true + } + + // Rewrite special resources. + switch tr.originEndpoint.ResourceType { + // Webhook configurations should be rewritten. + case "mutatingwebhookconfigurations", + "validatingwebhookconfigurations", + "clusterroles": + return true + } + + return false +} + +func (tr *TargetRequest) ResourceForLog() string { + if tr.webhookRule != nil { + return tr.webhookRule.Resource + } + if tr.originEndpoint != nil { + ep := tr.originEndpoint + if ep.IsRoot { + return "ROOT" + } + if ep.IsUnknown { + return "UKNOWN" + } + if ep.IsCore { + // /api + if ep.Version == "" { + return "APIVersions/core" + } + // /api/v1 + if ep.ResourceType == "" { + return "APIResourceList/core" + } + // /api/v1/RESOURCE/NAME/SUBRESOURCE + // /api/v1/namespaces/NS/status + // /api/v1/namespaces/NS/RESOURCE/NAME/SUBRESOURCE + if ep.Subresource != "" { + return ep.ResourceType + "/" + ep.Subresource + } + // /api/v1/RESOURCETYPE + // /api/v1/RESOURCETYPE/NAME + // /api/v1/namespaces + // /api/v1/namespaces/NAMESPACE + // /api/v1/namespaces/NAMESPACE/RESOURCETYPE + // /api/v1/namespaces/NAMESPACE/RESOURCETYPE/NAME + return ep.ResourceType + } + // /apis + if ep.Group == "" { + return "APIGroupList" + } + // /apis/GROUP + if ep.Version == "" { + return "APIGroup/" + ep.Group + } + // /apis/GROUP/VERSION + if ep.ResourceType == "" { + return "APIResourceList/" + ep.Group + } + // /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE + // /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE + if ep.Subresource != "" { + return ep.ResourceType + "/" + ep.Subresource + } + // /apis/GROUP/VERSION/RESOURCETYPE + // /apis/GROUP/VERSION/RESOURCETYPE/NAME + // /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE + // /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME + return ep.ResourceType + } + + return "UNKNOWN" +} diff --git a/images/kube-api-proxy/pkg/rewriter/webhook.go b/images/kube-api-proxy/pkg/rewriter/webhook.go new file mode 100644 index 000000000..4a51c74cb --- /dev/null +++ b/images/kube-api-proxy/pkg/rewriter/webhook.go @@ -0,0 +1 @@ +package rewriter diff --git a/images/kube-api-proxy/pkg/server/http_server.go b/images/kube-api-proxy/pkg/server/http_server.go new file mode 100644 index 000000000..5b0f8a653 --- /dev/null +++ b/images/kube-api-proxy/pkg/server/http_server.go @@ -0,0 +1,141 @@ +package server + +import ( + "context" + "crypto/tls" + "errors" + "fmt" + logutil "kube-api-proxy/pkg/log" + "kube-api-proxy/pkg/tls/certmanager" + log "log/slog" + "net" + "net/http" + "sync" +) + +// HTTPServer starts HTTP server with root handler using listen address. +// Implements Runnable interface to be able to stop server. +type HTTPServer struct { + InstanceDesc string + ListenAddr string + RootHandler http.Handler + CertManager certmanager.CertificateManager + Err error + + initLock sync.Mutex + stopped bool + + listener net.Listener + instance *http.Server +} + +// init checks if listen is possible and creates new HTTP server instance. +// initLock is used to avoid data races with the Stop method. +func (s *HTTPServer) init() bool { + s.initLock.Lock() + defer s.initLock.Unlock() + if s.stopped { + // Stop was called earlier. + return false + } + + l, err := net.Listen("tcp", s.ListenAddr) + if err != nil { + s.Err = err + log.Error(fmt.Sprintf("%s: listen on %s err: %s", s.InstanceDesc, s.ListenAddr, err)) + return false + } + s.listener = l + log.Info(fmt.Sprintf("%s: listen for incoming requests on %s", s.InstanceDesc, s.ListenAddr)) + + mux := http.NewServeMux() + mux.Handle("/", s.RootHandler) + + s.instance = &http.Server{ + Handler: mux, + } + return true +} + +func (s *HTTPServer) Start() { + if !s.init() { + return + } + + // Start serving HTTP requests, block until server instance stops or returns an error. + var err error + if s.CertManager != nil { + go s.CertManager.Start() + s.setupTLS() + err = s.instance.ServeTLS(s.listener, "", "") + } else { + err = s.instance.Serve(s.listener) + } + // Ignore closed error: it's a consequence of stop. + if err != nil { + switch { + case errors.Is(err, http.ErrServerClosed): + case errors.Is(err, net.ErrClosed): + default: + s.Err = err + } + } + return +} + +func (s *HTTPServer) setupTLS() { + s.instance.TLSConfig = &tls.Config{ + GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { + cert := s.CertManager.Current() + if cert == nil { + return nil, errors.New("no server certificate, server is not yet ready to receive traffic") + } + return cert, nil + }, + } +} + +// Stop shutdowns HTTP server instance and close a done channel. +// Stop and init may be run in parallel, so initLock is used to wait until +// variables are initialized. +func (s *HTTPServer) Stop() { + s.initLock.Lock() + defer s.initLock.Unlock() + + if s.stopped { + return + } + s.stopped = true + + if s.CertManager != nil { + s.CertManager.Stop() + } + // Shutdown instance if it was initialized. + if s.instance != nil { + log.Info(fmt.Sprintf("%s: stop", s.InstanceDesc)) + err := s.instance.Shutdown(context.Background()) + // Ignore ErrClosed. + if err != nil { + switch { + case errors.Is(err, http.ErrServerClosed): + case errors.Is(err, net.ErrClosed): + case s.Err != nil: + // log error to not reset runtime error. + log.Error(fmt.Sprintf("%s: stop instance", s.InstanceDesc), logutil.SlogErr(err)) + default: + s.Err = err + } + } + } +} + +// ConstructListenAddr return ip:port with defaults. +func ConstructListenAddr(addr, port, defaultAddr, defaultPort string) string { + if addr == "" { + addr = defaultAddr + } + if port == "" { + port = defaultPort + } + return addr + ":" + port +} diff --git a/images/kube-api-proxy/pkg/server/runnable_group.go b/images/kube-api-proxy/pkg/server/runnable_group.go new file mode 100644 index 000000000..e60120423 --- /dev/null +++ b/images/kube-api-proxy/pkg/server/runnable_group.go @@ -0,0 +1,74 @@ +package server + +import ( + "sync" +) + +type Runnable interface { + Start() + Stop() +} + +// RunnableGroup is a group of Runnables that should run until one of them stops. +type RunnableGroup struct { + runnables []Runnable +} + +func NewRunnableGroup() *RunnableGroup { + return &RunnableGroup{ + runnables: make([]Runnable, 0), + } +} + +// Add register Runnable in a group. +// Note: not designed for parallel registering. +func (rg *RunnableGroup) Add(r Runnable) { + rg.runnables = append(rg.runnables, r) +} + +// Start starts all Runnables and stops all of them when at least one Runnable stops. +func (rg *RunnableGroup) Start() { + // Start all runnables. + oneStoppedCh := rg.startAll() + + // Block until one runnable is stopped. + <-oneStoppedCh + + // Wait until all Runnables stop. + rg.stopAll() +} + +// startAll calls Start for each Runnable in separate go routines. +// It waits until all go routines starts. +// It returns a channel, so caller can receive event when one of the Runnables stops. +func (rg *RunnableGroup) startAll() chan struct{} { + oneStopped := make(chan struct{}) + var closeOnce sync.Once + + for i := range rg.runnables { + r := rg.runnables[i] + go func() { + r.Start() + closeOnce.Do(func() { + close(oneStopped) + }) + }() + } + + return oneStopped +} + +// stopAll calls Stop for each Runnable in a separate go routine. +// It waits until all go routines starts. +func (rg *RunnableGroup) stopAll() { + var wg sync.WaitGroup + wg.Add(len(rg.runnables)) + for i := range rg.runnables { + r := rg.runnables[i] + go func() { + r.Stop() + wg.Done() + }() + } + wg.Wait() +} diff --git a/images/kube-api-proxy/pkg/target/kubernetes.go b/images/kube-api-proxy/pkg/target/kubernetes.go new file mode 100644 index 000000000..ad2757adc --- /dev/null +++ b/images/kube-api-proxy/pkg/target/kubernetes.go @@ -0,0 +1,39 @@ +package target + +import ( + "fmt" + "net/http" + "net/url" + + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client/config" +) + +type Kubernetes struct { + Config *rest.Config + Client *http.Client + APIServerURL *url.URL +} + +func NewKubernetesTarget() (*Kubernetes, error) { + var err error + k := &Kubernetes{} + + k.Config, err = config.GetConfig() + if err != nil { + return nil, fmt.Errorf("load Kubernetes client config: %w", err) + } + + // Configure HTTP client to Kubernetes API server. + k.Client, err = rest.HTTPClientFor(k.Config) + if err != nil { + return nil, fmt.Errorf("setup Kubernetes API http client: %w", err) + } + + k.APIServerURL, err = url.Parse(k.Config.Host) + if err != nil { + return nil, fmt.Errorf("parse API server URL: %w", err) + } + + return k, nil +} diff --git a/images/kube-api-proxy/pkg/target/webhook.go b/images/kube-api-proxy/pkg/target/webhook.go new file mode 100644 index 000000000..d3ebd31bd --- /dev/null +++ b/images/kube-api-proxy/pkg/target/webhook.go @@ -0,0 +1,89 @@ +package target + +import ( + "crypto/tls" + "fmt" + "kube-api-proxy/pkg/tls/certmanager" + "kube-api-proxy/pkg/tls/certmanager/filesystem" + "net" + "net/http" + "net/url" + "os" + "time" +) + +type Webhook struct { + Client *http.Client + URL *url.URL + CertManager certmanager.CertificateManager +} + +const ( + WebhookAddressVar = "WEBHOOK_ADDRESS" + WebhookServerNameVar = "WEBHOOK_SERVER_NAME" + WebhookCertFileVar = "WEBHOOK_CERT_FILE" + WebhookKeyFileVar = "WEBHOOK_KEY_FILE" +) + +var ( + defaultWebhookTimeout = 30 * time.Second + defaultWebhookAddress = "https://127.0.0.1:9443" +) + +func NewWebhookTarget() (*Webhook, error) { + var err error + webhook := &Webhook{} + + // Target address and serverName. + address := os.Getenv(WebhookAddressVar) + if address == "" { + address = defaultWebhookAddress + } + + serverName := os.Getenv(WebhookServerNameVar) + if serverName == "" { + serverName = address + } + + webhook.URL, err = url.Parse(address) + if err != nil { + return nil, err + } + + // Certificate settings. + certFile := os.Getenv(WebhookCertFileVar) + keyFile := os.Getenv(WebhookKeyFileVar) + if certFile == "" && keyFile != "" { + return nil, fmt.Errorf("should specify cert file in %s if %s is not empty", WebhookCertFileVar, WebhookKeyFileVar) + } + if certFile != "" && keyFile == "" { + return nil, fmt.Errorf("should specify key file in %s if %s is not empty", WebhookKeyFileVar, WebhookCertFileVar) + } + if certFile != "" && keyFile != "" { + webhook.CertManager = filesystem.NewFileCertificateManager(certFile, keyFile) + } + + // Construct TLS client without validation to connect to the local webhook server. + dialer := &net.Dialer{ + Timeout: defaultWebhookTimeout, + } + + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + ServerName: serverName, + }, + DisableKeepAlives: true, + IdleConnTimeout: 5 * time.Minute, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + DialContext: dialer.DialContext, + } + + webhook.Client = &http.Client{ + Transport: tr, + Timeout: defaultWebhookTimeout, + } + + return webhook, nil +} diff --git a/images/kube-api-proxy/pkg/tls/certmanager/certmanager.go b/images/kube-api-proxy/pkg/tls/certmanager/certmanager.go new file mode 100644 index 000000000..d182692b6 --- /dev/null +++ b/images/kube-api-proxy/pkg/tls/certmanager/certmanager.go @@ -0,0 +1,11 @@ +package certmanager + +import ( + "crypto/tls" +) + +type CertificateManager interface { + Start() + Stop() + Current() *tls.Certificate +} diff --git a/images/kube-api-proxy/pkg/tls/certmanager/filesystem/file-cert-manager.go b/images/kube-api-proxy/pkg/tls/certmanager/filesystem/file-cert-manager.go new file mode 100644 index 000000000..532c43a04 --- /dev/null +++ b/images/kube-api-proxy/pkg/tls/certmanager/filesystem/file-cert-manager.go @@ -0,0 +1,152 @@ +package filesystem + +import ( + "crypto/tls" + "fmt" + "github.com/fsnotify/fsnotify" + logutil "kube-api-proxy/pkg/log" + "kube-api-proxy/pkg/tls/util" + "log/slog" + "os" + "path/filepath" + "sync" + "time" +) + +type FileCertificateManager struct { + stopCh chan struct{} + certAccessLock sync.Mutex + cert *tls.Certificate + certBytesPath string + keyBytesPath string + errorRetryInterval time.Duration +} + +func NewFileCertificateManager(certBytesPath, keyBytesPath string) *FileCertificateManager { + return &FileCertificateManager{ + certBytesPath: certBytesPath, + keyBytesPath: keyBytesPath, + stopCh: make(chan struct{}), + errorRetryInterval: 1 * time.Minute, + } +} + +func (f *FileCertificateManager) Start() { + objectUpdated := make(chan struct{}, 1) + watcher, err := fsnotify.NewWatcher() + if err != nil { + slog.Error("failed to create an inotify watcher", logutil.SlogErr(err)) + } + defer watcher.Close() + + certDir := filepath.Dir(f.certBytesPath) + err = watcher.Add(certDir) + if err != nil { + slog.Error(fmt.Sprintf("failed to establish a watch on %s", f.certBytesPath), logutil.SlogErr(err)) + } + keyDir := filepath.Dir(f.keyBytesPath) + if keyDir != certDir { + err = watcher.Add(keyDir) + if err != nil { + slog.Error(fmt.Sprintf("failed to establish a watch on %s", f.keyBytesPath), logutil.SlogErr(err)) + } + } + + go func() { + for { + select { + case _, ok := <-watcher.Events: + if !ok { + return + } + select { + case objectUpdated <- struct{}{}: + default: + slog.Debug("Dropping redundant wakeup for cert reload") + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + slog.Error(fmt.Sprintf("An error occurred when watching certificates files %s and %s", f.certBytesPath, f.keyBytesPath), logutil.SlogErr(err)) + } + } + }() + + // ensure we load the certificates on startup + objectUpdated <- struct{}{} + +sync: + for { + select { + case <-objectUpdated: + if err := f.rotateCerts(); err != nil { + go func() { + time.Sleep(f.errorRetryInterval) + select { + case objectUpdated <- struct{}{}: + default: + slog.Debug("Dropping redundant wakeup for cert reload") + } + }() + } + case <-f.stopCh: + break sync + } + } +} + +func (f *FileCertificateManager) Stop() { + f.certAccessLock.Lock() + defer f.certAccessLock.Unlock() + select { + case <-f.stopCh: + default: + close(f.stopCh) + } +} + +func (f *FileCertificateManager) rotateCerts() error { + crt, err := f.loadCertificates() + if err != nil { + return fmt.Errorf("failed to load the certificate %s and %s: %w", f.certBytesPath, f.keyBytesPath, err) + } + + f.certAccessLock.Lock() + defer f.certAccessLock.Unlock() + // update after the callback, to ensure that the reconfiguration succeeded + f.cert = crt + slog.Info(fmt.Sprintf("certificate with common name '%s' retrieved.", crt.Leaf.Subject.CommonName)) + return nil +} + +func (f *FileCertificateManager) loadCertificates() (serverCrt *tls.Certificate, err error) { + // #nosec No risk for path injection. Used for specific cert file for key rotation + certBytes, err := os.ReadFile(f.certBytesPath) + if err != nil { + return nil, err + } + // #nosec No risk for path injection. Used for specific cert file for key rotation + keyBytes, err := os.ReadFile(f.keyBytesPath) + if err != nil { + return nil, err + } + + crt, err := tls.X509KeyPair(certBytes, keyBytes) + if err != nil { + return nil, fmt.Errorf("failed to load certificate: %w\n", err) + } + + leaf, err := util.ParseCertsPEM(certBytes) + if err != nil { + return nil, fmt.Errorf("failed to load leaf certificate: %w\n", err) + } + crt.Leaf = leaf[0] + return &crt, nil +} + +func (f *FileCertificateManager) Current() *tls.Certificate { + f.certAccessLock.Lock() + defer f.certAccessLock.Unlock() + return f.cert +} diff --git a/images/kube-api-proxy/pkg/tls/util/util.go b/images/kube-api-proxy/pkg/tls/util/util.go new file mode 100644 index 000000000..a6e27dd69 --- /dev/null +++ b/images/kube-api-proxy/pkg/tls/util/util.go @@ -0,0 +1,36 @@ +package util + +import ( + "crypto/x509" + "encoding/pem" + "errors" +) + +const CertificateBlockType string = "CERTIFICATE" + +func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) { + var certs []*x509.Certificate + for len(pemCerts) > 0 { + var block *pem.Block + block, pemCerts = pem.Decode(pemCerts) + if block == nil { + break + } + // Only use PEM "CERTIFICATE" blocks without extra headers + if block.Type != CertificateBlockType || len(block.Headers) != 0 { + continue + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return certs, err + } + + certs = append(certs, cert) + } + + if len(certs) == 0 { + return nil, errors.New("data does not contain any valid RSA or ECDSA certificates") + } + return certs, nil +} diff --git a/images/kube-api-proxy/werf.inc.yaml b/images/kube-api-proxy/werf.inc.yaml new file mode 100644 index 000000000..459209398 --- /dev/null +++ b/images/kube-api-proxy/werf.inc.yaml @@ -0,0 +1,39 @@ +--- +image: {{ $.ImageName }}-builder +fromImage: base-golang-21-bookworm +git: + - add: /images/{{ $.ImageName }} + to: /src/kube-api-proxy + stageDependencies: + install: + - go.mod + - go.sum + setup: + - "**/*.go" +mount: + - fromPath: ~/go-pkg-cache + to: /go/pkg +shell: + install: + - cd /src/kube-api-proxy + - go mod download + setup: + - cd /src/kube-api-proxy + - export GO111MODULE=on + - export GOOS=linux + - export CGO_ENABLED=0 + - export GOARCH=amd64 + - go build -v -a -o kube-api-proxy ./cmd/kube-api-proxy + +--- +image: {{ $.ImageName }} +fromImage: base-ubuntu-jammy +import: + - image: {{ $.ImageName }}-builder + add: /src/kube-api-proxy/kube-api-proxy + to: /app/kube-api-proxy + after: install +docker: + USER: "65532:65532" + WORKDIR: "/app" + ENTRYPOINT: ["/app/kube-api-proxy"] diff --git a/images/libguestfs/werf.inc.yaml b/images/libguestfs/werf.inc.yaml index ca0100d12..760b53540 100644 --- a/images/libguestfs/werf.inc.yaml +++ b/images/libguestfs/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/pre-delete-hook/entrypoint.sh b/images/pre-delete-hook/entrypoint.sh index de2c576a6..b0a404abc 100644 --- a/images/pre-delete-hook/entrypoint.sh +++ b/images/pre-delete-hook/entrypoint.sh @@ -1,13 +1,13 @@ #!/bin/bash set -eu -o pipefail -KUBEVIRT_RESOURCE="kubevirts.x.virtualization.deckhouse.io" +KUBEVIRT_RESOURCE="dvpinternalkubevirts.internal.virtualization.deckhouse.io" echo "Delete Kubevirt configuration ..." kubectl delete -n d8-virtualization ${KUBEVIRT_RESOURCE} kubevirt || true echo "Wait for Kubevirt deletion ..." kubectl wait --for=delete -n d8-virtualization ${KUBEVIRT_RESOURCE} kubevirt --timeout=180s || true -CDI_RESOURCE="cdis.x.virtualization.deckhouse.io" +CDI_RESOURCE="dvpinternalcdis.internal.virtualization.deckhouse.io" echo "Delete CDI configuration ..." kubectl delete ${CDI_RESOURCE} cdi || true echo "Wait for CDI deletion ..." diff --git a/images/virt-api/werf.inc.yaml b/images/virt-api/werf.inc.yaml index 0f698f4df..d7a6d107b 100644 --- a/images/virt-api/werf.inc.yaml +++ b/images/virt-api/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/virt-artifact/patches/010-override-crds.patch b/images/virt-artifact/patches/010-override-crds.patch deleted file mode 100644 index 11b2a5446..000000000 --- a/images/virt-artifact/patches/010-override-crds.patch +++ /dev/null @@ -1,992 +0,0 @@ -diff --git a/pkg/storage/export/export/export.go b/pkg/storage/export/export/export.go -index 51eb69df6..7a8a29381 100644 ---- a/pkg/storage/export/export/export.go -+++ b/pkg/storage/export/export/export.go -@@ -140,7 +140,7 @@ var exportGVK = schema.GroupVersionKind{ - } - - var datavolumeGVK = schema.GroupVersionKind{ -- Group: cdiv1.SchemeGroupVersion.Group, -+ Group: "x.virtualization.deckhouse.io", - Version: cdiv1.SchemeGroupVersion.Version, - Kind: "DataVolume", - } -diff --git a/pkg/storage/export/export/links.go b/pkg/storage/export/export/links.go -index 38bdb9410..5dfd44224 100644 ---- a/pkg/storage/export/export/links.go -+++ b/pkg/storage/export/export/links.go -@@ -32,6 +32,7 @@ import ( - corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" - -+ "kubevirt.io/api/export" - exportv1 "kubevirt.io/api/export/v1alpha1" - - "kubevirt.io/kubevirt/pkg/certificates/triple/cert" -@@ -45,7 +46,7 @@ const ( - routeCaKey = "ca.crt" - subjectAltNameId = "2.5.29.17" - -- apiGroup = "export.kubevirt.io" -+ apiGroup = export.GroupName - apiVersion = "v1alpha1" - exportResourceName = "virtualmachineexports" - gv = apiGroup + "/" + apiVersion -diff --git a/pkg/storage/export/virt-exportserver/exportserver.go b/pkg/storage/export/virt-exportserver/exportserver.go -index 388f9c752..8e20fe5c4 100644 ---- a/pkg/storage/export/virt-exportserver/exportserver.go -+++ b/pkg/storage/export/virt-exportserver/exportserver.go -@@ -579,7 +579,7 @@ func vmHandler(filePath string, vi []VolumeInfo, getBasePath func() (string, err - for _, dv := range datavolumes { - dv.TypeMeta = metav1.TypeMeta{ - Kind: "DataVolume", -- APIVersion: "cdi.kubevirt.io/v1beta1", -+ APIVersion: "x.virtualization.deckhouse.io/v1beta1", - } - for _, info := range vi { - if strings.Contains(info.RawGzURI, dv.Name) { -diff --git a/pkg/virt-api/definitions/definitions.go b/pkg/virt-api/definitions/definitions.go -index 94443cbe3..b71cca384 100644 ---- a/pkg/virt-api/definitions/definitions.go -+++ b/pkg/virt-api/definitions/definitions.go -@@ -55,8 +55,33 @@ const ( - ) - - func ComposeAPIDefinitions() []*restful.WebService { -- var result []*restful.WebService -- for _, f := range []func() []*restful.WebService{ -+ return xGVApiServiceDefinitions(v1.GroupVersion) -+} -+ -+func xGVApiServiceDefinitions(xGV schema.GroupVersion) []*restful.WebService { -+ ws := new(restful.WebService) -+ ws.Doc("The KubeVirt and CDI API, a virtual machine management.") -+ -+ ws.Route( -+ ws.GET("/").Produces(mime.MIME_JSON).Writes(metav1.APIResourceList{}). -+ To(noop). -+ Operation(fmt.Sprintf("getAPIResources-%s", xGV.Group)). -+ Doc("Get KubeVirt and CDI API Resources"). -+ Returns(http.StatusOK, "OK", metav1.APIResourceList{}). -+ Returns(http.StatusNotFound, "Not Found", ""), -+ ) -+ -+ ws2 := new(restful.WebService) -+ ws2.Path(GroupBasePath(xGV)) -+ ws2.Route(ws2.GET("/"). -+ Produces(mime.MIME_JSON).Writes(metav1.APIGroup{}). -+ To(noop). -+ Doc("Get a KubeVirt and CDI API group"). -+ Operation("getAPIGroup-"+xGV.Group). -+ Returns(http.StatusOK, "OK", metav1.APIGroup{}). -+ Returns(http.StatusNotFound, "Not Found", "")) -+ -+ for _, f := range []func(ws *restful.WebService) *restful.WebService{ - kubevirtApiServiceDefinitions, - snapshotApiServiceDefinitions, - exportApiServiceDefinitions, -@@ -65,13 +90,13 @@ func ComposeAPIDefinitions() []*restful.WebService { - poolApiServiceDefinitions, - vmCloneDefinitions, - } { -- result = append(result, f()...) -+ ws = f(ws) - } - -- return result -+ return []*restful.WebService{ws, ws2} - } - --func kubevirtApiServiceDefinitions() []*restful.WebService { -+func kubevirtApiServiceDefinitions(ws *restful.WebService) *restful.WebService { - vmiGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "virtualmachineinstances"} - vmirsGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "virtualmachineinstancereplicasets"} - vmipGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "virtualmachineinstancepresets"} -@@ -79,11 +104,7 @@ func kubevirtApiServiceDefinitions() []*restful.WebService { - migrationGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "virtualmachineinstancemigrations"} - kubeVirtGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "kubevirt"} - -- ws, err := groupVersionProxyBase(v1.GroupVersion) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericNamespacedResourceProxy(ws, kubeVirtGVR, &v1.KubeVirt{}, v1.KubeVirtGroupVersionKind.Kind, &v1.KubeVirtList{}) - if err != nil { - panic(err) -@@ -113,24 +134,15 @@ func kubevirtApiServiceDefinitions() []*restful.WebService { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(vmiGVR) -- if err != nil { -- panic(err) -- } -- -- return []*restful.WebService{ws, ws2} -+ return ws - } - --func snapshotApiServiceDefinitions() []*restful.WebService { -+func snapshotApiServiceDefinitions(ws *restful.WebService) *restful.WebService { - vmsGVR := snapshotv1.SchemeGroupVersion.WithResource("virtualmachinesnapshots") - vmscGVR := snapshotv1.SchemeGroupVersion.WithResource("virtualmachinesnapshotcontents") - vmrGVR := snapshotv1.SchemeGroupVersion.WithResource("virtualmachinerestores") - -- ws, err := groupVersionProxyBase(schema.GroupVersion{Group: snapshotv1.SchemeGroupVersion.Group, Version: snapshotv1.SchemeGroupVersion.Version}) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericNamespacedResourceProxy(ws, vmsGVR, &snapshotv1.VirtualMachineSnapshot{}, "VirtualMachineSnapshot", &snapshotv1.VirtualMachineSnapshotList{}) - if err != nil { - panic(err) -@@ -146,64 +158,40 @@ func snapshotApiServiceDefinitions() []*restful.WebService { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(vmsGVR) -- if err != nil { -- panic(err) -- } -- return []*restful.WebService{ws, ws2} -+ return ws - } - --func exportApiServiceDefinitions() []*restful.WebService { -+func exportApiServiceDefinitions(ws *restful.WebService) *restful.WebService { - exportsGVR := exportv1.SchemeGroupVersion.WithResource("virtualmachineexports") - -- ws, err := groupVersionProxyBase(schema.GroupVersion{Group: exportv1.SchemeGroupVersion.Group, Version: exportv1.SchemeGroupVersion.Version}) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericNamespacedResourceProxy(ws, exportsGVR, &exportv1.VirtualMachineExport{}, "VirtualMachineExport", &exportv1.VirtualMachineExportList{}) - if err != nil { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(exportsGVR) -- if err != nil { -- panic(err) -- } -- return []*restful.WebService{ws, ws2} -+ return ws - } - --func migrationPoliciesApiServiceDefinitions() []*restful.WebService { -+func migrationPoliciesApiServiceDefinitions(ws *restful.WebService) *restful.WebService { - mpGVR := migrationsv1.SchemeGroupVersion.WithResource(migrations.ResourceMigrationPolicies) - -- ws, err := groupVersionProxyBase(schema.GroupVersion{Group: migrationsv1.SchemeGroupVersion.Group, Version: migrationsv1.SchemeGroupVersion.Version}) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericClusterResourceProxy(ws, mpGVR, &migrationsv1.MigrationPolicy{}, migrationsv1.MigrationPolicyKind.Kind, &migrationsv1.MigrationPolicyList{}) - if err != nil { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(mpGVR) -- if err != nil { -- panic(err) -- } -- return []*restful.WebService{ws, ws2} -+ return ws - } - --func instancetypeApiServiceDefinitions() []*restful.WebService { -+func instancetypeApiServiceDefinitions(ws *restful.WebService) *restful.WebService { - instancetypeGVR := instancetypev1beta1.SchemeGroupVersion.WithResource(instancetype.PluralResourceName) - clusterInstancetypeGVR := instancetypev1beta1.SchemeGroupVersion.WithResource(instancetype.ClusterPluralResourceName) - preferenceGVR := instancetypev1beta1.SchemeGroupVersion.WithResource(instancetype.PluralPreferenceResourceName) - clusterPreferenceGVR := instancetypev1beta1.SchemeGroupVersion.WithResource(instancetype.ClusterPluralPreferenceResourceName) - -- ws, err := groupVersionProxyBase(instancetypev1beta1.SchemeGroupVersion) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericNamespacedResourceProxy(ws, instancetypeGVR, &instancetypev1beta1.VirtualMachineInstancetype{}, "VirtualMachineInstancetype", &instancetypev1beta1.VirtualMachineInstancetypeList{}) - if err != nil { - panic(err) -@@ -224,53 +212,31 @@ func instancetypeApiServiceDefinitions() []*restful.WebService { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(instancetypeGVR) -- if err != nil { -- panic(err) -- } -- -- return []*restful.WebService{ws, ws2} -+ return ws - } - --func poolApiServiceDefinitions() []*restful.WebService { -+func poolApiServiceDefinitions(ws *restful.WebService) *restful.WebService { - poolGVR := poolv1alpha1.SchemeGroupVersion.WithResource("virtualmachinepools") - -- ws, err := groupVersionProxyBase(poolv1alpha1.SchemeGroupVersion) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericNamespacedResourceProxy(ws, poolGVR, &poolv1alpha1.VirtualMachinePool{}, "VirtualMachinePool", &poolv1alpha1.VirtualMachinePoolList{}) - if err != nil { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(poolGVR) -- if err != nil { -- panic(err) -- } -- -- return []*restful.WebService{ws, ws2} -+ return ws - } - --func vmCloneDefinitions() []*restful.WebService { -+func vmCloneDefinitions(ws *restful.WebService) *restful.WebService { - mpGVR := clonev1lpha1.SchemeGroupVersion.WithResource(clone.ResourceVMClonePlural) - -- ws, err := groupVersionProxyBase(schema.GroupVersion{Group: clonev1lpha1.SchemeGroupVersion.Group, Version: clonev1lpha1.SchemeGroupVersion.Version}) -- if err != nil { -- panic(err) -- } -- -+ var err error - ws, err = genericClusterResourceProxy(ws, mpGVR, &clonev1lpha1.VirtualMachineClone{}, clonev1lpha1.VirtualMachineCloneKind.Kind, &clonev1lpha1.VirtualMachineCloneList{}) - if err != nil { - panic(err) - } - -- ws2, err := resourceProxyAutodiscovery(mpGVR) -- if err != nil { -- panic(err) -- } -- return []*restful.WebService{ws, ws2} -+ return ws - } - - func groupVersionProxyBase(gv schema.GroupVersion) (*restful.WebService, error) { -@@ -295,25 +261,25 @@ func genericNamespacedResourceProxy(ws *restful.WebService, gvr schema.GroupVers - listExample := reflect.ValueOf(objListPointer).Elem().Interface() - - ws.Route(addNamespaceParam(ws, -- createOperation(ws, NamespacedResourceBasePath(gvr), objExample). -+ createOperation(ws, BaseNamespacedResourceBasePath(gvr), objExample). - Operation("createNamespaced"+objKind). - Doc("Create a "+objKind+obj), - )) - - ws.Route(addNamespaceParam(ws, -- replaceOperation(ws, NamespacedResourcePath(gvr), objExample). -+ replaceOperation(ws, BaseNamespacedResourcePath(gvr), objExample). - Operation("replaceNamespaced"+objKind). - Doc("Update a "+objKind+obj), - )) - - ws.Route(addNamespaceParam(ws, -- deleteOperation(ws, NamespacedResourcePath(gvr)). -+ deleteOperation(ws, BaseNamespacedResourcePath(gvr)). - Operation("deleteNamespaced"+objKind). - Doc("Delete a "+objKind+obj), - )) - - ws.Route(addNamespaceParam(ws, -- readOperation(ws, NamespacedResourcePath(gvr), objExample). -+ readOperation(ws, BaseNamespacedResourcePath(gvr), objExample). - Operation("readNamespaced"+objKind). - Doc("Get a "+objKind+obj), - )) -@@ -325,7 +291,7 @@ func genericNamespacedResourceProxy(ws *restful.WebService, gvr schema.GroupVers - ) - - ws.Route(addNamespaceParam(ws, -- patchOperation(ws, NamespacedResourcePath(gvr), objExample). -+ patchOperation(ws, BaseNamespacedResourcePath(gvr), objExample). - Operation("patchNamespaced"+objKind). - Doc("Patch a "+objKind+obj), - )) -@@ -339,19 +305,19 @@ func genericNamespacedResourceProxy(ws *restful.WebService, gvr schema.GroupVers - - // TODO, implement watch. For now it is here to provide swagger doc only - ws.Route(addNamespaceParam(ws, -- watchOperation(ws, "/watch"+NamespacedResourceBasePath(gvr)). -+ watchOperation(ws, "/watch"+BaseNamespacedResourceBasePath(gvr)). - Operation("watchNamespaced"+objKind). - Doc(watch+objKind+obj), - )) - - ws.Route(addNamespaceParam(ws, -- listOperation(ws, NamespacedResourceBasePath(gvr), listExample). -+ listOperation(ws, BaseNamespacedResourceBasePath(gvr), listExample). - Operation("listNamespaced"+objKind). - Doc("Get a list of "+objKind+objs), - )) - - ws.Route( -- deleteCollectionOperation(ws, NamespacedResourceBasePath(gvr)). -+ deleteCollectionOperation(ws, BaseNamespacedResourceBasePath(gvr)). - Operation("deleteCollectionNamespaced" + objKind). - Doc("Delete a collection of " + objKind + objs), - ) -@@ -642,10 +608,22 @@ func GroupVersionBasePath(gvr schema.GroupVersion) string { - return fmt.Sprintf("/apis/%s/%s", gvr.Group, gvr.Version) - } - -+// BaseNamespacedResourceBasePath concatenates NamespacedResourceBasePath result with group version base prefix. -+// WebService no longer uses the root path with group version, so it's necessary to set group version path here. -+func BaseNamespacedResourceBasePath(gvr schema.GroupVersionResource) string { -+ return GroupVersionBasePath(gvr.GroupVersion()) + NamespacedResourceBasePath(gvr) -+} -+ - func NamespacedResourceBasePath(gvr schema.GroupVersionResource) string { - return fmt.Sprintf("/namespaces/{namespace:[a-z0-9][a-z0-9\\-]*}/%s", gvr.Resource) - } - -+// BaseNamespacedResourcePath concatenates NamespacedResourcePath result with group version base prefix. -+// WebService no longer uses the root path with group version, so it's necessary to set group version path here. -+func BaseNamespacedResourcePath(gvr schema.GroupVersionResource) string { -+ return GroupVersionBasePath(gvr.GroupVersion()) + NamespacedResourcePath(gvr) -+} -+ - func NamespacedResourcePath(gvr schema.GroupVersionResource) string { - return fmt.Sprintf("/namespaces/{namespace:[a-z0-9][a-z0-9\\-]*}/%s/{name:[a-z0-9][a-z0-9\\-]*}", gvr.Resource) - } -diff --git a/pkg/virt-controller/watch/clone/util.go b/pkg/virt-controller/watch/clone/util.go -index cb66290f7..9cce76b10 100644 ---- a/pkg/virt-controller/watch/clone/util.go -+++ b/pkg/virt-controller/watch/clone/util.go -@@ -16,12 +16,13 @@ import ( - "k8s.io/apimachinery/pkg/util/rand" - - clonev1alpha1 "kubevirt.io/api/clone/v1alpha1" -+ coreapi "kubevirt.io/api/core" - v1 "kubevirt.io/api/core/v1" - ) - - const ( - vmKind = "VirtualMachine" -- kubevirtApiGroup = "kubevirt.io" -+ kubevirtApiGroup = coreapi.GroupName - ) - - // variable so can be overridden in tests -diff --git a/pkg/virt-operator/resource/generate/components/crds.go b/pkg/virt-operator/resource/generate/components/crds.go -index 822f3d82b..23f3a96a6 100644 ---- a/pkg/virt-operator/resource/generate/components/crds.go -+++ b/pkg/virt-operator/resource/generate/components/crds.go -@@ -156,9 +156,9 @@ func NewVirtualMachineInstanceCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachineinstances", - Singular: "virtualmachineinstance", - Kind: virtv1.VirtualMachineInstanceGroupVersionKind.Kind, -- ShortNames: []string{"vmi", "vmis"}, -+ ShortNames: []string{"xvmi", "xvmis"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -194,9 +194,9 @@ func NewVirtualMachineCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachines", - Singular: "virtualmachine", - Kind: virtv1.VirtualMachineGroupVersionKind.Kind, -- ShortNames: []string{"vm", "vms"}, -+ ShortNames: []string{"xvm", "xvms"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -244,9 +244,9 @@ func NewPresetCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachineinstancepresets", - Singular: "virtualmachineinstancepreset", - Kind: virtv1.VirtualMachineInstancePresetGroupVersionKind.Kind, -- ShortNames: []string{"vmipreset", "vmipresets"}, -+ ShortNames: []string{"xvmipreset", "xvmipresets"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -271,9 +271,9 @@ func NewReplicaSetCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachineinstancereplicasets", - Singular: "virtualmachineinstancereplicaset", - Kind: virtv1.VirtualMachineInstanceReplicaSetGroupVersionKind.Kind, -- ShortNames: []string{"vmirs", "vmirss"}, -+ ShortNames: []string{"xvmirs", "xvmirss"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -316,9 +316,9 @@ func NewVirtualMachineInstanceMigrationCrd() (*extv1.CustomResourceDefinition, e - Plural: "virtualmachineinstancemigrations", - Singular: "virtualmachineinstancemigration", - Kind: virtv1.VirtualMachineInstanceMigrationGroupVersionKind.Kind, -- ShortNames: []string{"vmim", "vmims"}, -+ ShortNames: []string{"xvmim", "xvmims"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -370,9 +370,9 @@ func NewKubeVirtCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "kubevirts", - Singular: "kubevirt", - Kind: virtv1.KubeVirtGroupVersionKind.Kind, -- ShortNames: []string{"kv", "kvs"}, -+ ShortNames: []string{"xkv", "xkvs"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -411,9 +411,9 @@ func NewVirtualMachinePoolCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachinepools", - Singular: "virtualmachinepool", - Kind: "VirtualMachinePool", -- ShortNames: []string{"vmpool", "vmpools"}, -+ ShortNames: []string{"xvmpool", "xvmpools"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -463,9 +463,9 @@ func NewVirtualMachineSnapshotCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachinesnapshots", - Singular: "virtualmachinesnapshot", - Kind: "VirtualMachineSnapshot", -- ShortNames: []string{"vmsnapshot", "vmsnapshots"}, -+ ShortNames: []string{"xvmsnapshot", "xvmsnapshots"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -505,9 +505,9 @@ func NewVirtualMachineSnapshotContentCrd() (*extv1.CustomResourceDefinition, err - Plural: "virtualmachinesnapshotcontents", - Singular: "virtualmachinesnapshotcontent", - Kind: "VirtualMachineSnapshotContent", -- ShortNames: []string{"vmsnapshotcontent", "vmsnapshotcontents"}, -+ ShortNames: []string{"xvmsnapshotcontent", "xvmsnapshotcontents"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -544,9 +544,9 @@ func NewVirtualMachineRestoreCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachinerestores", - Singular: "virtualmachinerestore", - Kind: "VirtualMachineRestore", -- ShortNames: []string{"vmrestore", "vmrestores"}, -+ ShortNames: []string{"xvmrestore", "xvmrestores"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -585,9 +585,9 @@ func NewVirtualMachineExportCrd() (*extv1.CustomResourceDefinition, error) { - Plural: "virtualmachineexports", - Singular: "virtualmachineexport", - Kind: "VirtualMachineExport", -- ShortNames: []string{"vmexport", "vmexports"}, -+ ShortNames: []string{"xvmexport", "xvmexports"}, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -@@ -615,9 +615,9 @@ func NewVirtualMachineInstancetypeCrd() (*extv1.CustomResourceDefinition, error) - Names: extv1.CustomResourceDefinitionNames{ - Plural: instancetype.PluralResourceName, - Singular: instancetype.SingularResourceName, -- ShortNames: []string{"vminstancetype", "vminstancetypes", "vmf", "vmfs"}, -+ ShortNames: []string{"xvminstancetype", "xvminstancetypes", "xvmf", "xvmfs"}, - Kind: "VirtualMachineInstancetype", -- Categories: []string{"all"}, -+ Categories: []string{"kubevirt"}, - }, - Scope: extv1.NamespaceScoped, - Conversion: &extv1.CustomResourceConversion{ -@@ -657,7 +657,7 @@ func NewVirtualMachineClusterInstancetypeCrd() (*extv1.CustomResourceDefinition, - Names: extv1.CustomResourceDefinitionNames{ - Plural: instancetype.ClusterPluralResourceName, - Singular: instancetype.ClusterSingularResourceName, -- ShortNames: []string{"vmclusterinstancetype", "vmclusterinstancetypes", "vmcf", "vmcfs"}, -+ ShortNames: []string{"xvmclusterinstancetype", "xvmclusterinstancetypes", "xvmcf", "xvmcfs"}, - Kind: "VirtualMachineClusterInstancetype", - }, - Scope: extv1.ClusterScoped, -@@ -698,9 +698,9 @@ func NewVirtualMachinePreferenceCrd() (*extv1.CustomResourceDefinition, error) { - Names: extv1.CustomResourceDefinitionNames{ - Plural: instancetype.PluralPreferenceResourceName, - Singular: instancetype.SingularPreferenceResourceName, -- ShortNames: []string{"vmpref", "vmprefs", "vmp", "vmps"}, -+ ShortNames: []string{"xvmpref", "xvmprefs", "xvmp", "xvmps"}, - Kind: "VirtualMachinePreference", -- Categories: []string{"all"}, -+ Categories: []string{"kubevirt"}, - }, - Scope: extv1.NamespaceScoped, - Conversion: &extv1.CustomResourceConversion{ -@@ -740,7 +740,7 @@ func NewVirtualMachineClusterPreferenceCrd() (*extv1.CustomResourceDefinition, e - Names: extv1.CustomResourceDefinitionNames{ - Plural: instancetype.ClusterPluralPreferenceResourceName, - Singular: instancetype.ClusterSingularPreferenceResourceName, -- ShortNames: []string{"vmcp", "vmcps"}, -+ ShortNames: []string{"xvmcp", "xvmcps"}, - Kind: "VirtualMachineClusterPreference", - }, - Scope: extv1.ClusterScoped, -@@ -827,10 +827,10 @@ func NewVirtualMachineCloneCrd() (*extv1.CustomResourceDefinition, error) { - Names: extv1.CustomResourceDefinitionNames{ - Plural: clone.ResourceVMClonePlural, - Singular: clone.ResourceVMCloneSingular, -- ShortNames: []string{"vmclone", "vmclones"}, -+ ShortNames: []string{"xvmclone", "xvmclones"}, - Kind: clonev1alpha1.VirtualMachineCloneKind.Kind, - Categories: []string{ -- "all", -+ "kubevirt", - }, - }, - } -diff --git a/pkg/virt-operator/resource/generate/rbac/apiserver.go b/pkg/virt-operator/resource/generate/rbac/apiserver.go -index 99e8fe12d..1f409c28c 100644 ---- a/pkg/virt-operator/resource/generate/rbac/apiserver.go -+++ b/pkg/virt-operator/resource/generate/rbac/apiserver.go -@@ -28,14 +28,16 @@ import ( - - "kubevirt.io/kubevirt/pkg/virt-operator/resource/generate/components" - -+ coreapi "kubevirt.io/api/core" - virtv1 "kubevirt.io/api/core/v1" - "kubevirt.io/api/migrations" -+ snapshotapi "kubevirt.io/api/snapshot" - ) - - const ( - VersionName = "rbac.authorization.k8s.io" - VersionNamev1 = "rbac.authorization.k8s.io/v1" -- GroupName = "kubevirt.io" -+ GroupName = coreapi.GroupName - ) - - func GetAllApiServer(namespace string) []runtime.Object { -@@ -195,7 +197,7 @@ func newApiServerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "snapshot.kubevirt.io", -+ snapshotapi.GroupName, - }, - Resources: []string{ - "virtualmachinesnapshots", -@@ -208,7 +210,7 @@ func newApiServerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "cdi.kubevirt.io", -+ "x.virtualization.deckhouse.io", - }, - Resources: []string{ - "datasources", -@@ -233,7 +235,7 @@ func newApiServerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "instancetype.kubevirt.io", -+ instancetype.GroupName, - }, - Resources: []string{ - instancetype.PluralResourceName, -diff --git a/pkg/virt-operator/resource/generate/rbac/cluster.go b/pkg/virt-operator/resource/generate/rbac/cluster.go -index 1af14cb60..82659d6f8 100644 ---- a/pkg/virt-operator/resource/generate/rbac/cluster.go -+++ b/pkg/virt-operator/resource/generate/rbac/cluster.go -@@ -28,15 +28,20 @@ import ( - virtv1 "kubevirt.io/api/core/v1" - - "kubevirt.io/api/migrations" -+ -+ cloneapi "kubevirt.io/api/clone" -+ exportapi "kubevirt.io/api/export" -+ poolapi "kubevirt.io/api/pool" -+ snapshotapi "kubevirt.io/api/snapshot" - ) - - const ( - GroupNameSubresources = "subresources.kubevirt.io" -- GroupNameSnapshot = "snapshot.kubevirt.io" -- GroupNameExport = "export.kubevirt.io" -- GroupNameClone = "clone.kubevirt.io" -- GroupNameInstancetype = "instancetype.kubevirt.io" -- GroupNamePool = "pool.kubevirt.io" -+ GroupNameSnapshot = snapshotapi.GroupName -+ GroupNameExport = exportapi.GroupName -+ GroupNameClone = cloneapi.GroupName -+ GroupNameInstancetype = instancetype.GroupName -+ GroupNamePool = poolapi.GroupName - NameDefault = "kubevirt.io:default" - VMInstancesGuestOSInfo = "virtualmachineinstances/guestosinfo" - VMInstancesFileSysList = "virtualmachineinstances/filesystemlist" -diff --git a/pkg/virt-operator/resource/generate/rbac/controller.go b/pkg/virt-operator/resource/generate/rbac/controller.go -index 474ab93b0..b7a1e2a55 100644 ---- a/pkg/virt-operator/resource/generate/rbac/controller.go -+++ b/pkg/virt-operator/resource/generate/rbac/controller.go -@@ -28,7 +28,11 @@ import ( - - "kubevirt.io/kubevirt/pkg/virt-operator/resource/generate/components" - -+ coreapi "kubevirt.io/api/core" -+ "kubevirt.io/api/export" - "kubevirt.io/api/instancetype" -+ "kubevirt.io/api/pool" -+ "kubevirt.io/api/snapshot" - - virtv1 "kubevirt.io/api/core/v1" - "kubevirt.io/api/migrations" -@@ -311,7 +315,7 @@ func newControllerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "snapshot.kubevirt.io", -+ snapshot.GroupName, - }, - Resources: []string{ - "*", -@@ -322,7 +326,7 @@ func newControllerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "export.kubevirt.io", -+ export.GroupName, - }, - Resources: []string{ - "*", -@@ -333,7 +337,7 @@ func newControllerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "pool.kubevirt.io", -+ pool.GroupName, - }, - Resources: []string{ - "virtualmachinepools", -@@ -354,7 +358,7 @@ func newControllerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "kubevirt.io", -+ coreapi.GroupName, - }, - Resources: []string{ - "*", -@@ -380,7 +384,7 @@ func newControllerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "cdi.kubevirt.io", -+ "x.virtualization.deckhouse.io", - }, - Resources: []string{ - "*", -@@ -468,7 +472,7 @@ func newControllerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "instancetype.kubevirt.io", -+ instancetype.GroupName, - }, - Resources: []string{ - instancetype.PluralResourceName, -diff --git a/pkg/virt-operator/resource/generate/rbac/exportproxy.go b/pkg/virt-operator/resource/generate/rbac/exportproxy.go -index 071ed91f9..bcfe70f36 100644 ---- a/pkg/virt-operator/resource/generate/rbac/exportproxy.go -+++ b/pkg/virt-operator/resource/generate/rbac/exportproxy.go -@@ -24,7 +24,9 @@ import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - -+ coreapi "kubevirt.io/api/core" - virtv1 "kubevirt.io/api/core/v1" -+ "kubevirt.io/api/export" - ) - - const ExportProxyServiceAccountName = "kubevirt-exportproxy" -@@ -70,7 +72,7 @@ func newExportProxyClusterRole() *rbacv1.ClusterRole { - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{ -- "export.kubevirt.io", -+ export.GroupName, - }, - Resources: []string{ - "virtualmachineexports", -@@ -81,7 +83,7 @@ func newExportProxyClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "kubevirt.io", -+ coreapi.GroupName, - }, - Resources: []string{ - "kubevirts", -diff --git a/pkg/virt-operator/resource/generate/rbac/handler.go b/pkg/virt-operator/resource/generate/rbac/handler.go -index e55a4044e..a953a5929 100644 ---- a/pkg/virt-operator/resource/generate/rbac/handler.go -+++ b/pkg/virt-operator/resource/generate/rbac/handler.go -@@ -25,6 +25,7 @@ import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - -+ coreapi "kubevirt.io/api/core" - virtv1 "kubevirt.io/api/core/v1" - "kubevirt.io/api/migrations" - -@@ -72,7 +73,7 @@ func newHandlerClusterRole() *rbacv1.ClusterRole { - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{ -- "kubevirt.io", -+ coreapi.GroupName, - }, - Resources: []string{ - "virtualmachineinstances", -@@ -134,7 +135,7 @@ func newHandlerClusterRole() *rbacv1.ClusterRole { - }, - { - APIGroups: []string{ -- "kubevirt.io", -+ coreapi.GroupName, - }, - Resources: []string{ - "kubevirts", -diff --git a/pkg/virt-operator/resource/generate/rbac/operator.go b/pkg/virt-operator/resource/generate/rbac/operator.go -index 98939edde..fd6e72c5c 100644 ---- a/pkg/virt-operator/resource/generate/rbac/operator.go -+++ b/pkg/virt-operator/resource/generate/rbac/operator.go -@@ -25,6 +25,7 @@ import ( - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - -+ coreapi "kubevirt.io/api/core" - virtv1 "kubevirt.io/api/core/v1" - - "kubevirt.io/kubevirt/pkg/virt-operator/resource/generate/components" -@@ -83,7 +84,7 @@ func NewOperatorClusterRole() *rbacv1.ClusterRole { - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{ -- "kubevirt.io", -+ coreapi.GroupName, - }, - Resources: []string{ - "kubevirts", -diff --git a/pkg/virtctl/create/clone/clone.go b/pkg/virtctl/create/clone/clone.go -index d82de56b9..fae2a0aad 100644 ---- a/pkg/virtctl/create/clone/clone.go -+++ b/pkg/virtctl/create/clone/clone.go -@@ -28,6 +28,8 @@ import ( - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/rand" - clonev1alpha1 "kubevirt.io/api/clone/v1alpha1" -+ coreapi "kubevirt.io/api/core" -+ "kubevirt.io/api/snapshot" - "kubevirt.io/client-go/kubecli" - - "kubevirt.io/kubevirt/pkg/pointer" -@@ -248,14 +250,14 @@ func (c *createClone) typeToTypedLocalObjectReference(sourceOrTargetType, source - switch sourceOrTargetType { - case "vm", "VM", "VirtualMachine", "virtualmachine": - kind = "VirtualMachine" -- apiGroup = "kubevirt.io" -+ apiGroup = coreapi.GroupName - case "snapshot", "VirtualMachineSnapshot", "vmsnapshot", "VMSnapshot": - if !isSource { - return nil, generateErr() - } - - kind = "VirtualMachineSnapshot" -- apiGroup = "snapshot.kubevirt.io" -+ apiGroup = snapshot.GroupName - default: - return nil, generateErr() - } -diff --git a/staging/src/kubevirt.io/api/clone/register.go b/staging/src/kubevirt.io/api/clone/register.go -index 85a24c26e..faa19eed5 100644 ---- a/staging/src/kubevirt.io/api/clone/register.go -+++ b/staging/src/kubevirt.io/api/clone/register.go -@@ -21,7 +21,7 @@ package clone - - // GroupName is the group name used in this package - const ( -- GroupName = "clone.kubevirt.io" -+ GroupName = "x.virtualization.deckhouse.io" - LatestVersion = "v1alpha1" - Kind = "VirtualMachineClone" - ListKind = "VirtualMachineCloneList" -diff --git a/staging/src/kubevirt.io/api/core/register.go b/staging/src/kubevirt.io/api/core/register.go -index 22080c717..56b23f7d7 100644 ---- a/staging/src/kubevirt.io/api/core/register.go -+++ b/staging/src/kubevirt.io/api/core/register.go -@@ -1,4 +1,4 @@ - package core - - // GroupName is the group name use in this package --const GroupName = "kubevirt.io" -+const GroupName = "x.virtualization.deckhouse.io" -diff --git a/staging/src/kubevirt.io/api/export/register.go b/staging/src/kubevirt.io/api/export/register.go -index 844dbf5e0..82f95d730 100644 ---- a/staging/src/kubevirt.io/api/export/register.go -+++ b/staging/src/kubevirt.io/api/export/register.go -@@ -21,5 +21,5 @@ package export - - // GroupName is the group name used in this package - const ( -- GroupName = "export.kubevirt.io" -+ GroupName = "x.virtualization.deckhouse.io" - ) -diff --git a/staging/src/kubevirt.io/api/instancetype/register.go b/staging/src/kubevirt.io/api/instancetype/register.go -index d4eafd31f..cffbb27f5 100644 ---- a/staging/src/kubevirt.io/api/instancetype/register.go -+++ b/staging/src/kubevirt.io/api/instancetype/register.go -@@ -21,7 +21,7 @@ package instancetype - - // GroupName is the group name used in this package - const ( -- GroupName = "instancetype.kubevirt.io" -+ GroupName = "x.virtualization.deckhouse.io" - - SingularResourceName = "virtualmachineinstancetype" - PluralResourceName = SingularResourceName + "s" -diff --git a/staging/src/kubevirt.io/api/migrations/register.go b/staging/src/kubevirt.io/api/migrations/register.go -index dbb6d3c41..03d40a9c2 100644 ---- a/staging/src/kubevirt.io/api/migrations/register.go -+++ b/staging/src/kubevirt.io/api/migrations/register.go -@@ -21,7 +21,7 @@ package migrations - - // GroupName is the group name used in this package - const ( -- GroupName = "migrations.kubevirt.io" -+ GroupName = "x.virtualization.deckhouse.io" - Version = "v1alpha1" - - ResourceMigrationPolicies = "migrationpolicies" -diff --git a/staging/src/kubevirt.io/api/pool/register.go b/staging/src/kubevirt.io/api/pool/register.go -index 08b9d8c62..9f45555b2 100644 ---- a/staging/src/kubevirt.io/api/pool/register.go -+++ b/staging/src/kubevirt.io/api/pool/register.go -@@ -21,5 +21,5 @@ package pool - - // GroupName is the group name used in this package - const ( -- GroupName = "pool.kubevirt.io" -+ GroupName = "x.virtualization.deckhouse.io" - ) -diff --git a/staging/src/kubevirt.io/api/snapshot/register.go b/staging/src/kubevirt.io/api/snapshot/register.go -index 880a59292..4a1216cb8 100644 ---- a/staging/src/kubevirt.io/api/snapshot/register.go -+++ b/staging/src/kubevirt.io/api/snapshot/register.go -@@ -21,5 +21,5 @@ package snapshot - - // GroupName is the group name used in this package - const ( -- GroupName = "snapshot.kubevirt.io" -+ GroupName = "x.virtualization.deckhouse.io" - ) -diff --git a/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/scheme/register.go b/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/scheme/register.go -index 3ac7803dd..66a3c3a43 100644 ---- a/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/scheme/register.go -+++ b/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/scheme/register.go -@@ -31,10 +31,6 @@ import ( - var Scheme = runtime.NewScheme() - var Codecs = serializer.NewCodecFactory(Scheme) - var ParameterCodec = runtime.NewParameterCodec(Scheme) --var localSchemeBuilder = runtime.SchemeBuilder{ -- cdiv1beta1.AddToScheme, -- uploadv1beta1.AddToScheme, --} - - // AddToScheme adds all types of this clientset into the given scheme. This allows composition - // of clientsets, like in: -@@ -50,9 +46,44 @@ var localSchemeBuilder = runtime.SchemeBuilder{ - // - // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types - // correctly. --var AddToScheme = localSchemeBuilder.AddToScheme -+var AddToScheme func(scheme *runtime.Scheme) error - - func init() { -+ cdiv1beta1.SchemeGroupVersion.Group = "x.virtualization.deckhouse.io" -+ cdiv1beta1.CDIGroupVersionKind.Group = "x.virtualization.deckhouse.io" -+ cdiv1beta1.SchemeBuilder = runtime.NewSchemeBuilder(func(scheme *runtime.Scheme) error { -+ scheme.AddKnownTypes(cdiv1beta1.SchemeGroupVersion, -+ &cdiv1beta1.DataVolume{}, -+ &cdiv1beta1.DataVolumeList{}, -+ &cdiv1beta1.CDIConfig{}, -+ &cdiv1beta1.CDIConfigList{}, -+ &cdiv1beta1.CDI{}, -+ &cdiv1beta1.CDIList{}, -+ &cdiv1beta1.StorageProfile{}, -+ &cdiv1beta1.StorageProfileList{}, -+ &cdiv1beta1.DataSource{}, -+ &cdiv1beta1.DataSourceList{}, -+ &cdiv1beta1.DataImportCron{}, -+ &cdiv1beta1.DataImportCronList{}, -+ &cdiv1beta1.ObjectTransfer{}, -+ &cdiv1beta1.ObjectTransferList{}, -+ &cdiv1beta1.VolumeImportSource{}, -+ &cdiv1beta1.VolumeImportSourceList{}, -+ &cdiv1beta1.VolumeUploadSource{}, -+ &cdiv1beta1.VolumeUploadSourceList{}, -+ &cdiv1beta1.VolumeCloneSource{}, -+ &cdiv1beta1.VolumeCloneSourceList{}, -+ ) -+ v1.AddToGroupVersion(scheme, cdiv1beta1.SchemeGroupVersion) -+ return nil -+ }) -+ cdiv1beta1.AddToScheme = cdiv1beta1.SchemeBuilder.AddToScheme -+ -+ AddToScheme = (&runtime.SchemeBuilder{ -+ cdiv1beta1.AddToScheme, -+ uploadv1beta1.AddToScheme, -+ }).AddToScheme -+ - v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - utilruntime.Must(AddToScheme(Scheme)) - } -diff --git a/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/typed/core/v1beta1/core_client.go b/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/typed/core/v1beta1/core_client.go -index 2fd57771a..03660be5c 100644 ---- a/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/typed/core/v1beta1/core_client.go -+++ b/staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/typed/core/v1beta1/core_client.go -@@ -113,6 +113,7 @@ func New(c rest.Interface) *CdiV1beta1Client { - - func setConfigDefaults(config *rest.Config) error { - gv := v1beta1.SchemeGroupVersion -+ gv.Group = "x.virtualization.deckhouse.io" - config.GroupVersion = &gv - config.APIPath = "/apis" - config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() diff --git a/images/virt-artifact/patches/012-support-kubeconfig-env.patch b/images/virt-artifact/patches/012-support-kubeconfig-env.patch new file mode 100644 index 000000000..529bd113b --- /dev/null +++ b/images/virt-artifact/patches/012-support-kubeconfig-env.patch @@ -0,0 +1,13 @@ +diff --git a/staging/src/kubevirt.io/client-go/kubecli/kubecli.go b/staging/src/kubevirt.io/client-go/kubecli/kubecli.go +index f5d3982a8..719717247 100644 +--- a/staging/src/kubevirt.io/client-go/kubecli/kubecli.go ++++ b/staging/src/kubevirt.io/client-go/kubecli/kubecli.go +@@ -99,7 +99,7 @@ var once sync.Once + // the different controller generators which normally add these flags too. + func Init() { + if flag.CommandLine.Lookup("kubeconfig") == nil { +- flag.StringVar(&kubeconfig, "kubeconfig", "", "absolute path to the kubeconfig file") ++ flag.StringVar(&kubeconfig, "kubeconfig", os.Getenv("KUBECONFIG"), "absolute path to the kubeconfig file") + } + if flag.CommandLine.Lookup("master") == nil { + flag.StringVar(&master, "master", "", "master url") diff --git a/images/virt-artifact/patches/README.md b/images/virt-artifact/patches/README.md index 30df45cbc..ead6ec3a4 100644 --- a/images/virt-artifact/patches/README.md +++ b/images/virt-artifact/patches/README.md @@ -26,11 +26,8 @@ The provided fix will always run the job in same place where virt-operator runs - https://github.com/kubevirt/kubevirt/pull/9360 -#### `010-override-crds.patch` - -Rename group name for all kubevirt CRDs to override them with deckhouse virtualization CRDs. - -Also, remove short names and change categories. Just in case. - #### `011-virt-api-authentication.patch` -Added the ability for virt-api to authenticate clients with certificates signed by our rootCA located in the config-map virtualization-ca. \ No newline at end of file +Added the ability for virt-api to authenticate clients with certificates signed by our rootCA located in the config-map virtualization-ca. + +#### `012-support-kubeconfig-env.patch` +Support `KUBECONFIG` environment variable. diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 6ad72e2da..fe6d1440c 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -3,7 +3,7 @@ {{- $builderImage := "quay.io/kubevirt/builder:2306070730-a3b45da40" }} {{- $version := "1.0.0" }} -artifact: {{ $.ImageName }} +image: {{ $.ImageName }} from: {{ $builderImage }} git: - add: /images/{{ $.ImageName }} @@ -19,7 +19,11 @@ shell: setup: - git clone --depth 1 --branch v{{ $version }} https://github.com/kubevirt/kubevirt.git /kubevirt - cd /kubevirt - - git apply /patches/*.patch + - | + for p in /patches/*.patch ; do + echo -n "Apply ${p} ... " + git apply ${p} || echo FAIL && echo OK + done - mkdir -p _out - echo "========== Build kubevirt images ============" - make bazel-build-image-bundle KUBEVIRT_RUN_UNNESTED=true diff --git a/images/virt-controller/werf.inc.yaml b/images/virt-controller/werf.inc.yaml index dc6f53664..5506075b1 100644 --- a/images/virt-controller/werf.inc.yaml +++ b/images/virt-controller/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/virt-exportproxy/werf.inc.yaml b/images/virt-exportproxy/werf.inc.yaml index c543cfcf3..6026a127b 100644 --- a/images/virt-exportproxy/werf.inc.yaml +++ b/images/virt-exportproxy/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/virt-exportserver/werf.inc.yaml b/images/virt-exportserver/werf.inc.yaml index a26b639b2..96af74ff6 100644 --- a/images/virt-exportserver/werf.inc.yaml +++ b/images/virt-exportserver/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/virt-handler/werf.inc.yaml b/images/virt-handler/werf.inc.yaml index ac79ddde1..bd2ef733f 100644 --- a/images/virt-handler/werf.inc.yaml +++ b/images/virt-handler/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/virt-launcher/werf.inc.yaml b/images/virt-launcher/werf.inc.yaml index c809a3778..723029cb1 100644 --- a/images/virt-launcher/werf.inc.yaml +++ b/images/virt-launcher/werf.inc.yaml @@ -2,7 +2,7 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' diff --git a/images/virt-operator/werf.inc.yaml b/images/virt-operator/werf.inc.yaml index c738559f0..e4ec6dbe6 100644 --- a/images/virt-operator/werf.inc.yaml +++ b/images/virt-operator/werf.inc.yaml @@ -2,13 +2,13 @@ image: {{ $.ImageName }} fromImage: base-scratch import: -- artifact: virt-artifact +- image: virt-artifact add: /images/kubevirt/{{ $.ImageName }}:latest excludePaths: - 'sys' to: / before: setup -- artifact: virt-artifact +- image: virt-artifact add: / to: / includePaths: diff --git a/images/virtualization-artifact/DEVELOPMENT.md b/images/virtualization-artifact/DEVELOPMENT.md index 720e37f31..c9c711117 100644 --- a/images/virtualization-artifact/DEVELOPMENT.md +++ b/images/virtualization-artifact/DEVELOPMENT.md @@ -37,17 +37,17 @@ docker login dev-registry.deckhouse.io task dev:logs ``` -3. Tasks to test CVMI/VMI +3. Tasks to test CVI/VI -Create ClusterVirtualMachineImage to import ubuntu ISO into DVCR: +Create ClusterVirtualImage to import ubuntu ISO into DVCR: ``` - task cvmi:recreate + task cvi:recreate ``` -Watch CVMI resource: +Watch CVI resource: ``` - task cvmi:watch + task cvi:watch ``` @@ -106,7 +106,7 @@ Set default context or use kubeswitch to switch to remote cluster context. 3. Run VM -Create ClusterVirtualMachineImage with alpine ISO from Caddy, VirtualMachineImage with 10Gb capacity and a VirtualMachine with 4 CPUs: +Create ClusterVirtualImage with alpine ISO from Caddy, VirtualImage with 10Gb capacity and a VirtualMachine with 4 CPUs: ``` kubectl create ns vm @@ -123,10 +123,10 @@ NAME PHASE virtualmachine.virtualization.deckhouse.io/linux-vm Running NAME CAPACITY PHASE PROGRESS -virtualmachinedisk.virtualization.deckhouse.io/linux-disk 10Gi Ready +virtualdisk.virtualization.deckhouse.io/linux-disk 10Gi Ready NAME CDROM PHASE PROGRESS -clustervirtualmachineimage.virtualization.deckhouse.io/linux-iso false Ready +clustervirtualimage.virtualization.deckhouse.io/linux-iso false Ready ``` 5. Access VM @@ -165,7 +165,7 @@ Repo contains Taskfile.dist.yaml. You can define your own tasks in [Taskfile.my. - `task dev:reset` — recreate k3d cluster and registry - `task build:cache:reset` — recreate build cache for virtualization-controller (requires after significant changes in go.mod) - `task kctl` — shortcut for `kubectl -n virtualization-controller` -- `task gen:api` — run k8s code-generator to generate DeepCopy methods +- `task task api:generate` — run k8s code-generator to generate DeepCopy methods - `task lint` — run Go linters - `task dev:update:crds` — apply all manifests from `api` directory - `task dev:update:` — apply CRD manifest from `api` directory. Short names are: cvmi, vmi, vmd, vmds, vm. @@ -175,7 +175,7 @@ Repo contains Taskfile.dist.yaml. You can define your own tasks in [Taskfile.my. - Define YAML manifest "by hands" in `api` directory. - Define Go structures in `api/` directory. -- Run `task gen:api` to generate DeepCopy methods. +- Run `task api:generate` to generate DeepCopy methods. - Add new types into addKnownTypes method in the `api//register.go` file. - Use type in Watch calls during controller setup. @@ -183,4 +183,4 @@ Repo contains Taskfile.dist.yaml. You can define your own tasks in [Taskfile.my. `task dev:converge` will copy YAML manifests from the `api` directory into `local/virtualization-controller/crds` directory before installing Helm chart. -Helm only install new CRDs. It will not update CRDs on `helm update`, as it is dangerous to automate (see [Helm docs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations)). After making changes of YAML manifests, use `task dev:update:crds` to apply all manifests in the `api` directory or use CRD short name to update individual CRD, e.g. run `task dev:update:cvmi` to update `customresourcedefinition.apiextensions.k8s.io/ClusterVirtualMachineImage`. +Helm only install new CRDs. It will not update CRDs on `helm update`, as it is dangerous to automate (see [Helm docs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations)). After making changes of YAML manifests, use `task dev:update:crds` to apply all manifests in the `api` directory or use CRD short name to update individual CRD, e.g. run `task dev:update:cvmi` to update `customresourcedefinition.apiextensions.k8s.io/ClusterVirtualImage`. diff --git a/images/virtualization-artifact/Taskfile.cvmi.yaml b/images/virtualization-artifact/Taskfile.cvmi.yaml index 7db29c1b7..3866a0b64 100644 --- a/images/virtualization-artifact/Taskfile.cvmi.yaml +++ b/images/virtualization-artifact/Taskfile.cvmi.yaml @@ -10,7 +10,7 @@ tasks: CVMI_FILE: '{{ .CVMI_FILE | default "config/samples/cvmi_ubuntu_iso.yaml" }}' cmds: - | - kubectl delete clustervirtualmachineimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} || true + kubectl delete clustervirtualimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} || true kubectl delete -n virtualization-controller po/importer-{{ .CVMI_NAME }} || true sleep 1 kubectl apply -f {{ .CVMI_FILE }} @@ -21,9 +21,9 @@ tasks: CVMI_NAME: '{{ .CVMI_NAME | default "ubuntu-iso" }}' cmds: - | - kubectl get clustervirtualmachineimage.virtualization.deckhouse.io -o wide | head -n1 + kubectl get clustervirtualimage.virtualization.deckhouse.io -o wide | head -n1 for i in `seq 1 400` ; do - kubectl get clustervirtualmachineimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} --no-headers -o wide || true + kubectl get clustervirtualimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} --no-headers -o wide || true sleep 2 done @@ -33,9 +33,9 @@ tasks: CVMI_NAME: '{{ .CVMI_NAME | default "ubuntu-iso" }}' cmds: - | - kubectl get clustervirtualmachineimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} || true + kubectl get clustervirtualimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} || true echo ">>> Annotations:" - (kubectl get clustervirtualmachineimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} -o json | jq '.metadata.annotations') || true + (kubectl get clustervirtualimage.virtualization.deckhouse.io/{{ .CVMI_NAME }} -o json | jq '.metadata.annotations') || true echo ">>> Importer Pod" kubectl -n virtualization-controller get po/importer-{{.CVMI_NAME}} || true diff --git a/images/virtualization-artifact/Taskfile.dist.yaml b/images/virtualization-artifact/Taskfile.dist.yaml index 15b135e71..fb9f01b19 100644 --- a/images/virtualization-artifact/Taskfile.dist.yaml +++ b/images/virtualization-artifact/Taskfile.dist.yaml @@ -527,22 +527,22 @@ tasks: - task: dev:update:vmipl dev:update:cvmi: - desc: "Update ClusterVirtualMachineImage CRD" + desc: "Update ClusterVirtualImage CRD" cmds: - - kubectl apply -f api/crds/clustervirtualmachineimage.yaml + - kubectl apply -f api/crds/clustervirtualimage.yaml dev:update:vmi: - desc: "Update VirtualMachineImage CRD" + desc: "Update VirtualImage CRD" cmds: - - kubectl apply -f api/crds/virtualmachineimage.yaml + - kubectl apply -f api/crds/virtualimage.yaml dev:update:vmd: - desc: "Update VirtualMachineDisk CRD" + desc: "Update VirtualDisk CRD" cmds: - - kubectl apply -f api/crds/virtualmachinedisk.yaml + - kubectl apply -f api/crds/virtualdisk.yaml dev:update:vmds: - desc: "Update VirtualMachineDiskSnapshot CRD" + desc: "Update VirtualDiskSnapshot CRD" cmds: - kubectl apply -f api/crds/virtualmachinedisksnapshot.yaml diff --git a/images/virtualization-artifact/Taskfile.vmi.yaml b/images/virtualization-artifact/Taskfile.vmi.yaml index 24fdb1421..e4ba53684 100644 --- a/images/virtualization-artifact/Taskfile.vmi.yaml +++ b/images/virtualization-artifact/Taskfile.vmi.yaml @@ -4,13 +4,13 @@ silent: true tasks: recreate: - desc: "Recreate example VMI resource in default namespace" + desc: "Recreate example VI resource in default namespace" vars: VMI_NAME: '{{ .VMI_NAME | default "ubuntu-iso" }}' VMI_FILE: '{{ .VMI_FILE | default "config/samples/vmi_ubuntu_registry.yaml" }}' cmds: - | - kubectl delete virtualmachineimage/{{ .VMI_NAME }} || true + kubectl delete virtualimage/{{ .VMI_NAME }} || true kubectl delete po/importer-{{ .VMI_NAME }} || true sleep 1 kubectl apply -f local/virtualization-controller/templates/dvcr-auth-secret.yaml || true @@ -22,10 +22,10 @@ tasks: VMI_NAME: '{{ .VMI_NAME | default "ubuntu-iso" }}' cmds: - | - kubectl get virtualmachineimage -o wide | head -n1 + kubectl get virtualimage -o wide | head -n1 for i in `seq 1 400` ; do - kubectl get virtualmachineimage/{{ .VMI_NAME }} --no-headers -o wide || true - kubectl get virtualmachineimage/{{ .VMI_NAME }} --no-headers || true + kubectl get virtualimage/{{ .VMI_NAME }} --no-headers -o wide || true + kubectl get virtualimage/{{ .VMI_NAME }} --no-headers || true sleep 2 done @@ -35,9 +35,9 @@ tasks: VMI_NAME: '{{ .VMI_NAME | default "ubuntu-iso" }}' cmds: - | - kubectl get virtualmachineimage/{{ .VMI_NAME }} || true + kubectl get virtualimage/{{ .VMI_NAME }} || true echo ">>> Annotations:" - (kubectl get virtualmachineimage/{{ .VMI_NAME }} -o json | jq '.metadata.annotations') || true + (kubectl get virtualimage/{{ .VMI_NAME }} -o json | jq '.metadata.annotations') || true echo ">>> DataVolumes" kubectl get datavolume echo ">>> PVCs" @@ -46,7 +46,7 @@ tasks: kubectl get po/importer-{{.VMI_NAME}} || true pvc:recreate: - desc: "Recreate example VMI resource" + desc: "Recreate example VI resource" cmds: - task: vmi:recreate vars: diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index 83e8750e9..a15447df5 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -11,9 +11,7 @@ import ( "go.uber.org/zap/zapcore" extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" apiruntime "k8s.io/apimachinery/pkg/runtime" - apiruntimeschema "k8s.io/apimachinery/pkg/runtime/schema" clientgoscheme "k8s.io/client-go/kubernetes/scheme" virtv1 "kubevirt.io/api/core/v1" cdiv1beta1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" @@ -47,18 +45,13 @@ var ( ) const ( - defaultVerbosity = "1" - kubevirtCoreGroupName = "x.virtualization.deckhouse.io" - cdiCoreGroupName = "x.virtualization.deckhouse.io" + defaultVerbosity = "1" ) func init() { importerImage = getRequiredEnvVar(common.ImporterPodImageNameVar) uploaderImage = getRequiredEnvVar(common.UploaderPodImageNameVar) controllerNamespace = getRequiredEnvVar(common.PodNamespaceVar) - - overrideKubevirtCoreGroupName(kubevirtCoreGroupName) - overrideCDICoreGroupName(cdiCoreGroupName) } func setupLogger() { @@ -99,61 +92,6 @@ func getRequiredEnvVar(name string) string { return val } -func overrideKubevirtCoreGroupName(groupName string) { - virtv1.GroupVersion.Group = groupName - virtv1.SchemeGroupVersion.Group = groupName - virtv1.StorageGroupVersion.Group = groupName - for i := range virtv1.GroupVersions { - virtv1.GroupVersions[i].Group = groupName - } - - virtv1.VirtualMachineInstanceGroupVersionKind.Group = groupName - virtv1.VirtualMachineInstanceReplicaSetGroupVersionKind.Group = groupName - virtv1.VirtualMachineInstancePresetGroupVersionKind.Group = groupName - virtv1.VirtualMachineGroupVersionKind.Group = groupName - virtv1.VirtualMachineInstanceMigrationGroupVersionKind.Group = groupName - virtv1.KubeVirtGroupVersionKind.Group = groupName - - virtv1.SchemeBuilder = apiruntime.NewSchemeBuilder(virtv1.AddKnownTypesGenerator([]apiruntimeschema.GroupVersion{virtv1.GroupVersion})) - virtv1.AddToScheme = virtv1.SchemeBuilder.AddToScheme -} - -func overrideCDICoreGroupName(groupName string) { - cdiv1beta1.SchemeGroupVersion.Group = groupName - cdiv1beta1.CDIGroupVersionKind.Group = groupName - - cdiv1beta1.SchemeBuilder = apiruntime.NewSchemeBuilder(addKnownTypes) - cdiv1beta1.AddToScheme = cdiv1beta1.SchemeBuilder.AddToScheme -} - -// Adds the list of known types to Scheme. -func addKnownTypes(scheme *apiruntime.Scheme) error { - scheme.AddKnownTypes(cdiv1beta1.SchemeGroupVersion, - &cdiv1beta1.DataVolume{}, - &cdiv1beta1.DataVolumeList{}, - &cdiv1beta1.CDIConfig{}, - &cdiv1beta1.CDIConfigList{}, - &cdiv1beta1.CDI{}, - &cdiv1beta1.CDIList{}, - &cdiv1beta1.StorageProfile{}, - &cdiv1beta1.StorageProfileList{}, - &cdiv1beta1.DataSource{}, - &cdiv1beta1.DataSourceList{}, - &cdiv1beta1.DataImportCron{}, - &cdiv1beta1.DataImportCronList{}, - &cdiv1beta1.ObjectTransfer{}, - &cdiv1beta1.ObjectTransferList{}, - &cdiv1beta1.VolumeImportSource{}, - &cdiv1beta1.VolumeImportSourceList{}, - &cdiv1beta1.VolumeUploadSource{}, - &cdiv1beta1.VolumeUploadSourceList{}, - &cdiv1beta1.VolumeCloneSource{}, - &cdiv1beta1.VolumeCloneSourceList{}, - ) - metav1.AddToGroupVersion(scheme, cdiv1beta1.SchemeGroupVersion) - return nil -} - func main() { flag.Parse() @@ -172,6 +110,8 @@ func main() { log.Error(err, "") os.Exit(1) } + // Override content type to JSON so proxy can rewrite payloads. + cfg.ContentType = apiruntime.ContentTypeJSON leaderElectionNS := os.Getenv(common.PodNamespaceVar) if leaderElectionNS == "" { diff --git a/images/virtualization-artifact/config/samples/cvmi_debian_iso.yaml b/images/virtualization-artifact/config/samples/cvmi_debian_iso.yaml index d620859f8..b95b242db 100644 --- a/images/virtualization-artifact/config/samples/cvmi_debian_iso.yaml +++ b/images/virtualization-artifact/config/samples/cvmi_debian_iso.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: debian-iso annotations: diff --git a/images/virtualization-artifact/config/samples/cvmi_debian_iso_ca_bundle.yaml b/images/virtualization-artifact/config/samples/cvmi_debian_iso_ca_bundle.yaml index d732ffa52..de2ee8506 100644 --- a/images/virtualization-artifact/config/samples/cvmi_debian_iso_ca_bundle.yaml +++ b/images/virtualization-artifact/config/samples/cvmi_debian_iso_ca_bundle.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: debian-iso annotations: diff --git a/images/virtualization-artifact/config/samples/cvmi_ubuntu_iso.yaml b/images/virtualization-artifact/config/samples/cvmi_ubuntu_iso.yaml index 92a1f590b..d47356f17 100644 --- a/images/virtualization-artifact/config/samples/cvmi_ubuntu_iso.yaml +++ b/images/virtualization-artifact/config/samples/cvmi_ubuntu_iso.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: ubuntu-iso spec: diff --git a/images/virtualization-artifact/config/samples/cvmi_upload.yaml b/images/virtualization-artifact/config/samples/cvmi_upload.yaml index 5f5375b12..cb8c9f0cd 100644 --- a/images/virtualization-artifact/config/samples/cvmi_upload.yaml +++ b/images/virtualization-artifact/config/samples/cvmi_upload.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: cvmi-upload annotations: diff --git a/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_disk.yaml b/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_disk.yaml index 5a132ec96..c2cdb823f 100644 --- a/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_disk.yaml +++ b/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_disk.yaml @@ -1,11 +1,11 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: linux-disk spec: persistentVolumeClaim: size: 10Gi - storageClassName: local-path + storageClass: local-path dataSource: type: HTTP http: @@ -30,7 +30,6 @@ spec: cores: 2 memory: size: 2Gi - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: linux-disk + blockDeviceRefs: + - kind: VirtualDisk + name: linux-disk diff --git a/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_image.yaml b/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_image.yaml index e704d6c60..21252e82a 100644 --- a/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_image.yaml +++ b/images/virtualization-artifact/config/samples/linux_vm_from_cloudimage_image.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: linux-image spec: @@ -13,17 +13,17 @@ spec: url: "http://caddy.caddy.svc.cluster.local/images/ubuntu-22.04-minimal-cloudimg-amd64.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: linux-disk namespace: vms spec: persistentVolumeClaim: size: 10Gi - storageClassName: local-path + storageClass: local-path dataSource: - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: + type: ClusterVirtualImage + clusterVirtualImage: name: linux-image --- apiVersion: virtualization.deckhouse.io/v1alpha2 @@ -41,7 +41,6 @@ spec: cores: 2 memory: size: 2Gi - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: linux-disk + blockDeviceRefs: + - kind: VirtualDisk + name: linux-disk diff --git a/images/virtualization-artifact/config/samples/linux_vm_from_iso_image.yaml b/images/virtualization-artifact/config/samples/linux_vm_from_iso_image.yaml index 70aa9b073..0fd8fdc48 100644 --- a/images/virtualization-artifact/config/samples/linux_vm_from_iso_image.yaml +++ b/images/virtualization-artifact/config/samples/linux_vm_from_iso_image.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: linux-iso annotations: @@ -11,13 +11,13 @@ spec: url: "http://caddy.caddy.svc.cluster.local/images/alpine-standard-3.18.2-x86_64.iso" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: linux-disk spec: persistentVolumeClaim: size: 10Gi - storageClassName: linstor-thin-data-r1 + storageClass: linstor-thin-data-r1 --- apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine @@ -33,11 +33,9 @@ spec: coreFraction: 50% memory: size: 6Gi - blockDevices: + blockDeviceRefs: # deattach it after install - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: linux-iso - - type: VirtualMachineDisk - virtualMachineDisk: - name: linux-disk + - kind: ClusterVirtualImage + name: linux-iso + - kind: VirtualDisk + name: linux-disk diff --git a/images/virtualization-artifact/config/samples/ubuntu_cloud_init.yaml b/images/virtualization-artifact/config/samples/ubuntu_cloud_init.yaml index fbd889a51..e61fdab59 100644 --- a/images/virtualization-artifact/config/samples/ubuntu_cloud_init.yaml +++ b/images/virtualization-artifact/config/samples/ubuntu_cloud_init.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: ubuntu spec: @@ -44,7 +44,6 @@ spec: coreFraction: 50% memory: size: 6Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: ubuntu + blockDeviceRefs: + - kind: VirtualImage + name: ubuntu diff --git a/images/virtualization-artifact/config/samples/virtual_machine_disk.yaml b/images/virtualization-artifact/config/samples/virtual_machine_disk.yaml index ec28ffad6..19a8d4f65 100644 --- a/images/virtualization-artifact/config/samples/virtual_machine_disk.yaml +++ b/images/virtualization-artifact/config/samples/virtual_machine_disk.yaml @@ -1,11 +1,11 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vmd-sample spec: persistentVolumeClaim: size: 10Gi - storageClassName: local-path + storageClass: local-path dataSource: type: "HTTP" http: diff --git a/images/virtualization-artifact/config/samples/vmbda.yaml b/images/virtualization-artifact/config/samples/vmbda.yaml index f19bdf9b0..8fac78e90 100644 --- a/images/virtualization-artifact/config/samples/vmbda.yaml +++ b/images/virtualization-artifact/config/samples/vmbda.yaml @@ -3,8 +3,8 @@ kind: VirtualMachineBlockDeviceAttachment metadata: name: vmd-blank-attachment spec: - virtualMachineName: linux-vm + virtualMachine: linux-vm blockDevice: - type: VirtualMachineDisk - virtualMachineDisk: + type: VirtualDisk + virtualDisk: name: vmd-blank diff --git a/images/virtualization-artifact/config/samples/vmd_blank.yaml b/images/virtualization-artifact/config/samples/vmd_blank.yaml index db5c2e649..9ce3d376d 100644 --- a/images/virtualization-artifact/config/samples/vmd_blank.yaml +++ b/images/virtualization-artifact/config/samples/vmd_blank.yaml @@ -1,8 +1,8 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vmd-blank spec: persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" size: "80M" diff --git a/images/virtualization-artifact/config/samples/vmd_http_auto_sized.yaml b/images/virtualization-artifact/config/samples/vmd_http_auto_sized.yaml index 647999303..db6a6a984 100644 --- a/images/virtualization-artifact/config/samples/vmd_http_auto_sized.yaml +++ b/images/virtualization-artifact/config/samples/vmd_http_auto_sized.yaml @@ -1,10 +1,10 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: debian-iso spec: persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" dataSource: type: "HTTP" http: diff --git a/images/virtualization-artifact/config/samples/vmd_http_sized.yaml b/images/virtualization-artifact/config/samples/vmd_http_sized.yaml index 3082337bc..5f86dbf87 100644 --- a/images/virtualization-artifact/config/samples/vmd_http_sized.yaml +++ b/images/virtualization-artifact/config/samples/vmd_http_sized.yaml @@ -1,10 +1,10 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: debian-iso spec: persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" size: "80Mi" dataSource: type: "HTTP" diff --git a/images/virtualization-artifact/config/samples/vmd_upload_auto_sized.yaml b/images/virtualization-artifact/config/samples/vmd_upload_auto_sized.yaml index c545b7673..d4fd397fe 100644 --- a/images/virtualization-artifact/config/samples/vmd_upload_auto_sized.yaml +++ b/images/virtualization-artifact/config/samples/vmd_upload_auto_sized.yaml @@ -1,9 +1,9 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vmd-upload-auto-sized spec: persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" dataSource: type: "Upload" diff --git a/images/virtualization-artifact/config/samples/vmd_upload_sized.yaml b/images/virtualization-artifact/config/samples/vmd_upload_sized.yaml index db9afb69a..331df4dc1 100644 --- a/images/virtualization-artifact/config/samples/vmd_upload_sized.yaml +++ b/images/virtualization-artifact/config/samples/vmd_upload_sized.yaml @@ -1,10 +1,10 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vmd-upload-sized spec: persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" size: "80Mi" dataSource: type: "Upload" diff --git a/images/virtualization-artifact/config/samples/vmi_ubuntu_2_phase.yaml b/images/virtualization-artifact/config/samples/vmi_ubuntu_2_phase.yaml index 9f845b189..ac6f7aa9d 100644 --- a/images/virtualization-artifact/config/samples/vmi_ubuntu_2_phase.yaml +++ b/images/virtualization-artifact/config/samples/vmi_ubuntu_2_phase.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: ubuntu-iso-pvc spec: @@ -8,7 +8,7 @@ spec: # 2. Import from Registry into PVC. storage: Kubernetes persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" dataSource: type: "HTTP" http: diff --git a/images/virtualization-artifact/config/samples/vmi_ubuntu_datavolume.yaml b/images/virtualization-artifact/config/samples/vmi_ubuntu_datavolume.yaml index fcbe7658c..09acab807 100644 --- a/images/virtualization-artifact/config/samples/vmi_ubuntu_datavolume.yaml +++ b/images/virtualization-artifact/config/samples/vmi_ubuntu_datavolume.yaml @@ -1,11 +1,11 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: ubuntu-iso-dv spec: storage: Kubernetes persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" dataSource: type: "ContainerImage" containerImage: diff --git a/images/virtualization-artifact/config/samples/vmi_ubuntu_registry.yaml b/images/virtualization-artifact/config/samples/vmi_ubuntu_registry.yaml index 09a11fcd1..c16e2b4b1 100644 --- a/images/virtualization-artifact/config/samples/vmi_ubuntu_registry.yaml +++ b/images/virtualization-artifact/config/samples/vmi_ubuntu_registry.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: ubuntu-iso spec: diff --git a/images/virtualization-artifact/config/samples/vmi_upload_datavolume.yaml b/images/virtualization-artifact/config/samples/vmi_upload_datavolume.yaml index 72b82b50c..8797358a3 100644 --- a/images/virtualization-artifact/config/samples/vmi_upload_datavolume.yaml +++ b/images/virtualization-artifact/config/samples/vmi_upload_datavolume.yaml @@ -1,10 +1,10 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: vmi-upload-dv spec: storage: Kubernetes persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" dataSource: type: "Upload" diff --git a/images/virtualization-artifact/config/samples/vmi_upload_registry.yaml b/images/virtualization-artifact/config/samples/vmi_upload_registry.yaml index 6ae3c7412..27f152dc1 100644 --- a/images/virtualization-artifact/config/samples/vmi_upload_registry.yaml +++ b/images/virtualization-artifact/config/samples/vmi_upload_registry.yaml @@ -1,10 +1,10 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: vmi-upload-cr spec: storage: ContainerRegistry persistentVolumeClaim: - storageClassName: "local-path" + storageClass: "local-path" dataSource: type: "Upload" diff --git a/images/virtualization-artifact/config/samples/win_vm_from_iso_image.yaml b/images/virtualization-artifact/config/samples/win_vm_from_iso_image.yaml index 5a8686a6f..91c88f3d2 100644 --- a/images/virtualization-artifact/config/samples/win_vm_from_iso_image.yaml +++ b/images/virtualization-artifact/config/samples/win_vm_from_iso_image.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-iso annotations: @@ -11,7 +11,7 @@ spec: url: "http://caddy.caddy.svc.cluster.local/images/win10.iso" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-virtio-iso annotations: @@ -23,13 +23,13 @@ spec: url: "http://caddy.caddy.svc.cluster.local/images/virtio-win-0.1.229.iso" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: win-disk spec: persistentVolumeClaim: size: 100Gi - storageClassName: local-path + storageClass: local-path --- apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine @@ -47,15 +47,12 @@ spec: memory: size: 8Gi enableParavirtualization: false - blockDevices: + blockDeviceRefs: # deattach it after install { - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-iso - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-virtio-iso + - kind: ClusterVirtualImage + name: win-iso + - kind: ClusterVirtualImage + name: win-virtio-iso # } deattach it after install - - type: VirtualMachineDisk - virtualMachineDisk: - name: win-disk + - kind: VirtualDisk + name: win-disk diff --git a/images/virtualization-artifact/config/vm_sysprep.yaml b/images/virtualization-artifact/config/vm_sysprep.yaml index 708e197c4..0a11a46fb 100644 --- a/images/virtualization-artifact/config/vm_sysprep.yaml +++ b/images/virtualization-artifact/config/vm_sysprep.yaml @@ -8,7 +8,7 @@ data: id_rsa.pub: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFDNnpkZ0ZpTHIxdUFLN1BkY2NoRGQrTHNlQTVmRU9jeENDdDdUTGxyN014Nmg4alVnK0crOEw5SkJOWnVEelRaU0YwZFI3cXd6ZEJCUWpvckFuWlRtWTNCaHNLY0ZyOEd0NEtNR3JTNnIzRE5tR3J1UDhHT1J2ZWdkV1p1WGdBU0tWcFhlSTduQ0lqUkp3QWFLMXgrZUdId0FXTzlaOG9oY2JvSGJMeWZmT29TWkRTSXVrMmtSSWM0NytFTlJqZzBUNngyVlJzcVgyN2c2ajREZlBLUVpHazB6dlhrWmFZdHIxZTJ0WmdxVEJXcVpVbG9NSks4bWlRcTZNa3RDS0FTNFZ0UGswazd0ZVFYNTdPR3dENkQ3dW80YitDbDhhWUFBd2huMGhjMEMyVVNmYnVWSGdxODhFU28yLytOd1Y0U1FjbDNzeENXMjF5R0lqQUd0NEh5N0oK --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-11-iso spec: @@ -18,7 +18,7 @@ spec: url: "https://software.download.prss.microsoft.com/dbazure/Win11_23H2_EnglishInternational_x64v2.iso?t=373e4da1-33cb-437a-8953-d2d82ffebc24&P1=1709887519&P2=601&P3=2&P4=tqE6F8wcrhc8F%2fU8sBkhHEuZD15Nd38TCvTKxzamX8FXI4ckmOZDzoXEdsX%2fHGU0To1bKXQq7fZkGtDMZM8SmcP9vPhWOXJwAZxuZEUk66TXbrHFWbi4txvK5%2f5FNNbGVMB1oBkEt%2f7rIYSRBofUXNtfZOD0mdlNl59Rww1Oufm9D5KTXWEJwK8imxbFwechKHhJewjt1KFcT%2bhfqh0YrWMPEdgU%2fVJom%2f5G2V2iFWZzZrCyZxsMSOtBM9OJxbmI6qXHzv36Fd7s3RyRQdMKww9s0OKaUEYuKtNBTJ0FaGxGEHjkslZmiqpXg%2bhZj%2bSUEgnVDlpb907qLMs4UeO4MQ%3d%3d" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: win-virtio-iso spec: @@ -28,14 +28,14 @@ spec: url: "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: vm-vmd namespace: default spec: persistentVolumeClaim: size: 50Gi - storageClassName: linstor-test-data-r1 + storageClass: linstor-test-data-r1 --- apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine @@ -46,8 +46,9 @@ metadata: vm: vm-sysprep spec: provisioning: - type: SysprepSecret - sysprepSecretRef: + type: SysprepRef + sysprepRef: + kind: Secret name: sysprep-config runPolicy: AlwaysOn osType: Windows @@ -58,13 +59,10 @@ spec: memory: size: 8Gi enableParavirtualization: true - blockDevices: - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-11-iso - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: win-virtio-iso - - type: VirtualMachineDisk - virtualMachineDisk: - name: vm-vmd + blockDeviceRefs: + - kind: ClusterVirtualImage + name: win-11-iso + - kind: ClusterVirtualImage + name: win-virtio-iso + - kind: VirtualDisk + name: vm-vmd diff --git a/images/virtualization-artifact/local/virtualization-controller/templates/validation-webhook.yaml b/images/virtualization-artifact/local/virtualization-controller/templates/validation-webhook.yaml index 0eaeb5a4b..aac040fe2 100644 --- a/images/virtualization-artifact/local/virtualization-controller/templates/validation-webhook.yaml +++ b/images/virtualization-artifact/local/virtualization-controller/templates/validation-webhook.yaml @@ -25,13 +25,13 @@ webhooks: - apiGroups: ["virtualization.deckhouse.io"] apiVersions: ["v1alpha2"] operations: ["CREATE", "UPDATE"] - resources: ["virtualmachinedisks"] + resources: ["virtualdisks"] scope: "Namespaced" clientConfig: service: namespace: virtualization-controller name: admission-webhook-service - path: /validate-virtualization-deckhouse-io-v1alpha2-virtualmachinedisk + path: /validate-virtualization-deckhouse-io-v1alpha2-virtualdisk port: 443 caBundle: | {{ .Files.Get "admission-webhook-certs/ca.pem" | b64enc }} diff --git a/images/virtualization-artifact/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go b/images/virtualization-artifact/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go index 208cc1612..8a7c03901 100644 --- a/images/virtualization-artifact/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go +++ b/images/virtualization-artifact/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go @@ -34,18 +34,18 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentBlockDevice": schema_virtualization_controller_api_core_v1alpha2_BlockDeviceAttachmentBlockDevice(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentVirtualMachineDisk": schema_virtualization_controller_api_core_v1alpha2_BlockDeviceAttachmentVirtualMachineDisk(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentVirtualDisk": schema_virtualization_controller_api_core_v1alpha2_BlockDeviceAttachmentVirtualDisk(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceSpec": schema_virtualization_controller_api_core_v1alpha2_BlockDeviceSpec(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceStatus": schema_virtualization_controller_api_core_v1alpha2_BlockDeviceStatus(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.CPUSpec": schema_virtualization_controller_api_core_v1alpha2_CPUSpec(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.CVMIDataSource": schema_virtualization_controller_api_core_v1alpha2_CVMIDataSource(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.Checksum": schema_virtualization_controller_api_core_v1alpha2_Checksum(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterImageDeviceSpec": schema_virtualization_controller_api_core_v1alpha2_ClusterImageDeviceSpec(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImage": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImage(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageList": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImageList(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageSpec": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImageSpec(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageStatus": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImageStatus(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceClusterVirtualMachineImage": schema_virtualization_controller_api_core_v1alpha2_DataSourceClusterVirtualMachineImage(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImage": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImage(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageList": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImageList(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageSpec": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImageSpec(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageStatus": schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImageStatus(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceClusterVirtualImage": schema_virtualization_controller_api_core_v1alpha2_DataSourceClusterVirtualImage(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceContainerRegistry": schema_virtualization_controller_api_core_v1alpha2_DataSourceContainerRegistry(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceHTTP": schema_virtualization_controller_api_core_v1alpha2_DataSourceHTTP(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNameNamespacedRef": schema_virtualization_controller_api_core_v1alpha2_DataSourceNameNamespacedRef(ref), @@ -62,9 +62,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.MemorySpec": schema_virtualization_controller_api_core_v1alpha2_MemorySpec(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.Provisioning": schema_virtualization_controller_api_core_v1alpha2_Provisioning(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMAffinity": schema_virtualization_controller_api_core_v1alpha2_VMAffinity(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDDataSource": schema_virtualization_controller_api_core_v1alpha2_VMDDataSource(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskDataSource": schema_virtualization_controller_api_core_v1alpha2_VirtualDiskDataSource(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDDownloadSpeed": schema_virtualization_controller_api_core_v1alpha2_VMDDownloadSpeed(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDPersistentVolumeClaim": schema_virtualization_controller_api_core_v1alpha2_VMDPersistentVolumeClaim(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskPersistentVolumeClaim": schema_virtualization_controller_api_core_v1alpha2_VirtualDiskPersistentVolumeClaim(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMIDataSource": schema_virtualization_controller_api_core_v1alpha2_VMIDataSource(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMIPersistentVolumeClaim": schema_virtualization_controller_api_core_v1alpha2_VMIPersistentVolumeClaim(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachine": schema_virtualization_controller_api_core_v1alpha2_VirtualMachine(ref), @@ -80,10 +80,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineCPUModelSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineCPUModelSpec(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineCPUModelStatus": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineCPUModelStatus(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineCPUModelStatusFeatures": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineCPUModelStatusFeatures(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDisk": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDisk(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskList": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskList(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskSpec(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskStatus": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskStatus(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDisk": schema_virtualization_controller_api_core_v1alpha2_VirtualDisk(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskList": schema_virtualization_controller_api_core_v1alpha2_VirtualDiskList(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualDiskSpec(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskStatus": schema_virtualization_controller_api_core_v1alpha2_VirtualDiskStatus(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineIPAddressClaim": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressClaim(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineIPAddressClaimList": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressClaimList(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineIPAddressClaimSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressClaimSpec(ref), @@ -93,10 +93,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineIPAddressLeaseList": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressLeaseList(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineIPAddressLeaseSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressLeaseSpec(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineIPAddressLeaseStatus": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressLeaseStatus(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImage": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImage(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageList": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageList(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageSpec(ref), - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageStatus": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageStatus(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImage": schema_virtualization_controller_api_core_v1alpha2_VirtualImage(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageList": schema_virtualization_controller_api_core_v1alpha2_VirtualImageList(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageSpec": schema_virtualization_controller_api_core_v1alpha2_VirtualImageSpec(ref), + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageStatus": schema_virtualization_controller_api_core_v1alpha2_VirtualImageStatus(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineList": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineList(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineOperation": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineOperation(ref), "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineOperationList": schema_virtualization_controller_api_core_v1alpha2_VirtualMachineOperationList(ref), @@ -642,21 +642,21 @@ func schema_virtualization_controller_api_core_v1alpha2_BlockDeviceAttachmentBlo Format: "", }, }, - "virtualMachineDisk": { + "virtualDisk": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentVirtualMachineDisk"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentVirtualDisk"), }, }, }, - Required: []string{"type", "virtualMachineDisk"}, + Required: []string{"type", "virtualDisk"}, }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentVirtualMachineDisk"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.BlockDeviceAttachmentVirtualDisk"}, } } -func schema_virtualization_controller_api_core_v1alpha2_BlockDeviceAttachmentVirtualMachineDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_BlockDeviceAttachmentVirtualDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -689,17 +689,17 @@ func schema_virtualization_controller_api_core_v1alpha2_BlockDeviceSpec(ref comm Format: "", }, }, - "virtualMachineImage": { + "virtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ImageDeviceSpec"), }, }, - "clusterVirtualMachineImage": { + "clusterVirtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterImageDeviceSpec"), }, }, - "virtualMachineDisk": { + "virtualDisk": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DiskDeviceSpec"), }, @@ -726,17 +726,17 @@ func schema_virtualization_controller_api_core_v1alpha2_BlockDeviceStatus(ref co Format: "", }, }, - "virtualMachineImage": { + "virtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ImageDeviceSpec"), }, }, - "clusterVirtualMachineImage": { + "clusterVirtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterImageDeviceSpec"), }, }, - "virtualMachineDisk": { + "virtualDisk": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DiskDeviceSpec"), }, @@ -763,7 +763,7 @@ func schema_virtualization_controller_api_core_v1alpha2_BlockDeviceStatus(ref co }, }, }, - Required: []string{"type", "virtualMachineImage", "clusterVirtualMachineImage", "virtualMachineDisk", "hotpluggable", "target", "size"}, + Required: []string{"type", "virtualImage", "clusterVirtualImage", "virtualDisk", "hotpluggable", "target", "size"}, }, }, Dependencies: []string{ @@ -827,12 +827,12 @@ func schema_virtualization_controller_api_core_v1alpha2_CVMIDataSource(ref commo Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceContainerRegistry"), }, }, - "virtualMachineImage": { + "virtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNameNamespacedRef"), }, }, - "clusterVirtualMachineImage": { + "clusterVirtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNamedRef"), }, @@ -889,11 +889,11 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterImageDeviceSpec(r } } -func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImage(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImage(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ClusterVirtualMachineImage is a cluster wide available image for virtual machines.", + Description: "ClusterVirtualImage is a cluster wide available image for virtual machines.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -919,13 +919,13 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma "spec": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageSpec"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageSpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageStatus"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageStatus"), }, }, }, @@ -933,15 +933,15 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageSpec", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageSpec", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } -func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ClusterVirtualMachineImageList provides the needed parameters to do request a list of ClusterVirtualMachineImages from the system.", + Description: "ClusterVirtualImageList provides the needed parameters to do request a list of ClusterVirtualImages from the system.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -972,7 +972,7 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImage"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImage"), }, }, }, @@ -983,11 +983,11 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualMachineImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.ClusterVirtualImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } -func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1008,7 +1008,7 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma } } -func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1041,7 +1041,7 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma }, "capacity": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -1101,7 +1101,7 @@ func schema_virtualization_controller_api_core_v1alpha2_ClusterVirtualMachineIma } } -func schema_virtualization_controller_api_core_v1alpha2_DataSourceClusterVirtualMachineImage(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_DataSourceClusterVirtualImage(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1376,7 +1376,7 @@ func schema_virtualization_controller_api_core_v1alpha2_ImageStatus(ref common.R }, "capacity": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -1528,7 +1528,7 @@ func schema_virtualization_controller_api_core_v1alpha2_ImageStatusTarget(ref co }, "persistentVolumeClaimName": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -1622,7 +1622,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VMAffinity(ref common.Re } } -func schema_virtualization_controller_api_core_v1alpha2_VMDDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualDiskDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1644,12 +1644,12 @@ func schema_virtualization_controller_api_core_v1alpha2_VMDDataSource(ref common Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceContainerRegistry"), }, }, - "virtualMachineImage": { + "virtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNamedRef"), }, }, - "clusterVirtualMachineImage": { + "clusterVirtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNamedRef"), }, @@ -1698,7 +1698,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VMDDownloadSpeed(ref com } } -func schema_virtualization_controller_api_core_v1alpha2_VMDPersistentVolumeClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualDiskPersistentVolumeClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1745,12 +1745,12 @@ func schema_virtualization_controller_api_core_v1alpha2_VMIDataSource(ref common Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceContainerRegistry"), }, }, - "virtualMachineImage": { + "virtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNamedRef"), }, }, - "clusterVirtualMachineImage": { + "clusterVirtualImage": { SchemaProps: spec.SchemaProps{ Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.DataSourceNamedRef"), }, @@ -2087,7 +2087,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineBlockDevic SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -2101,7 +2101,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineBlockDevic }, }, }, - Required: []string{"virtualMachineName", "blockDevice"}, + Required: []string{"virtualMachine", "blockDevice"}, }, }, Dependencies: []string{ @@ -2115,7 +2115,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineBlockDevic SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, Format: "", @@ -2366,11 +2366,11 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineCPUModelSt } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualDisk(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineDisk is a disk ready to be bound by a VM", + Description: "VirtualDisk is a disk ready to be bound by a VM", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -2396,13 +2396,13 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDisk(ref c "spec": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskSpec"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskSpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskStatus"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskStatus"), }, }, }, @@ -2410,15 +2410,15 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDisk(ref c }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskSpec", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDiskStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskSpec", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskList(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualDiskList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineDiskList contains a list of VirtualMachineDisk", + Description: "VirtualDiskList contains a list of VirtualDisk", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -2448,7 +2448,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskList(r Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDisk"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDisk"), }, }, }, @@ -2459,11 +2459,11 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskList(r }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineDisk", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDisk", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualDiskSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2471,13 +2471,13 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskSpec(r Properties: map[string]spec.Schema{ "dataSource": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDDataSource"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskDataSource"), }, }, "persistentVolumeClaim": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDPersistentVolumeClaim"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskPersistentVolumeClaim"), }, }, }, @@ -2485,11 +2485,11 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskSpec(r }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDDataSource", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VMDPersistentVolumeClaim"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskDataSource", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualDiskPersistentVolumeClaim"}, } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineDiskStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualDiskStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2664,7 +2664,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressC Description: "VirtualMachineIPAddressClaimSpec is the desired state of `VirtualMachineIPAddressClaim`.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "leaseName": { + "virtualMachineIPAddressLease": { SchemaProps: spec.SchemaProps{ Description: "The issued `VirtualMachineIPAddressLease`, managed automatically.", Default: "", @@ -2688,7 +2688,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressC }, }, }, - Required: []string{"leaseName", "address"}, + Required: []string{"virtualMachineIPAddressLease", "address"}, }, }, } @@ -2701,7 +2701,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressC Description: "VirtualMachineIPAddressClaimStatus is the observed state of `VirtualMachineIPAddressClaim`.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Description: "Represents the virtual machine that currently uses this IP address.", Type: []string{"string"}, @@ -2715,7 +2715,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressC Format: "", }, }, - "leaseName": { + "virtualMachineIPAddressLease": { SchemaProps: spec.SchemaProps{ Description: "The issued `VirtualMachineIPAddressLease`, managed automatically.", Type: []string{"string"}, @@ -2915,11 +2915,11 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineIPAddressL } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImage(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualImage(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineImage is an image for virtual machines available in the particular namespace.", + Description: "VirtualImage is an image for virtual machines available in the particular namespace.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -2945,13 +2945,13 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImage(ref "spec": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageSpec"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageSpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageStatus"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageStatus"), }, }, }, @@ -2959,15 +2959,15 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImage(ref }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageSpec", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageSpec", "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImageStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineImageList provides the needed parameters to do request a list of ClusterVirtualMachineImages from the system.", + Description: "VirtualImageList provides the needed parameters to do request a list of ClusterVirtualImages from the system.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -2998,7 +2998,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageList( Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImage"), + Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImage"), }, }, }, @@ -3009,11 +3009,11 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageList( }, }, Dependencies: []string{ - "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualMachineImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/deckhouse/virtualization-controller/api/core/v1alpha2.VirtualImage", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualImageSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -3047,7 +3047,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageSpec( } } -func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_virtualization_controller_api_core_v1alpha2_VirtualImageStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -3080,7 +3080,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineImageStatu }, "capacity": { SchemaProps: spec.SchemaProps{ - Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaimName", + Description: "FIXME: create ClusterImageStatus without Capacity and PersistentVolumeClaim", Type: []string{"string"}, Format: "", }, @@ -3299,7 +3299,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineOperationS Format: "", }, }, - "virtualMachineName": { + "virtualMachine": { SchemaProps: spec.SchemaProps{ Default: "", Type: []string{"string"}, @@ -3313,7 +3313,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineOperationS }, }, }, - Required: []string{"type", "virtualMachineName"}, + Required: []string{"type", "virtualMachine"}, }, }, } @@ -3365,9 +3365,9 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineSpec(ref c Format: "", }, }, - "virtualMachineIPAddressClaimName": { + "virtualMachineIPAddressClaim": { SchemaProps: spec.SchemaProps{ - Description: "VirtualMachineIPAddressClaimName specifies a name for the associated `VirtualMahcineIPAddressClaim` resource. Defaults to `{vm name}`.", + Description: "VirtualMachineIPAddressClaim specifies a name for the associated `VirtualMahcineIPAddressClaim` resource. Defaults to `{vm name}`.", Type: []string{"string"}, Format: "", }, @@ -3475,7 +3475,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineSpec(ref c Ref: ref("github.com/deckhouse/virtualization-controller/api/core/v1alpha2.MemorySpec"), }, }, - "blockDevices": { + "BlockDeviceRefs": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, Items: &spec.SchemaOrArray{ @@ -3501,7 +3501,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineSpec(ref c }, }, }, - Required: []string{"runPolicy", "priorityClassName", "disruptions", "enableParavirtualization", "cpu", "memory", "blockDevices", "provisioning"}, + Required: []string{"runPolicy", "priorityClassName", "disruptions", "enableParavirtualization", "cpu", "memory", "blockDeviceRefs", "provisioning"}, }, }, Dependencies: []string{ @@ -3543,7 +3543,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineStatus(ref Format: "", }, }, - "blockDevicesAttached": { + "BlockDeviceRefs": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, Items: &spec.SchemaOrArray{ @@ -3590,7 +3590,7 @@ func schema_virtualization_controller_api_core_v1alpha2_VirtualMachineStatus(ref }, }, }, - Required: []string{"phase", "nodeName", "ipAddressClaim", "ipAddress", "blockDevicesAttached", "guestOSInfo", "message", "restartID"}, + Required: []string{"phase", "nodeName", "ipAddressClaim", "ipAddress", "BlockDeviceRefs", "guestOSInfo", "message", "restartID"}, }, }, Dependencies: []string{ diff --git a/images/virtualization-artifact/pkg/apiserver/server/config.go b/images/virtualization-artifact/pkg/apiserver/server/config.go index b0c087209..bf0598adc 100644 --- a/images/virtualization-artifact/pkg/apiserver/server/config.go +++ b/images/virtualization-artifact/pkg/apiserver/server/config.go @@ -61,7 +61,7 @@ func (c Config) Complete() (*Server, error) { if err != nil { return nil, err } - vmInformer, err := informer.ForResource(virtv2.GroupVersionResource(virtv2.VMResource)) + vmInformer, err := informer.ForResource(virtv2.GroupVersionResource(virtv2.VirtualMachineResource)) if err != nil { return nil, err } @@ -73,7 +73,7 @@ func (c Config) Complete() (*Server, error) { if err != nil { return nil, err } - crd, err := kubeclient.CustomResourceDefinitions().Get(context.Background(), virtv2.Resource(virtv2.VMResource).String(), metav1.GetOptions{}) + crd, err := kubeclient.CustomResourceDefinitions().Get(context.Background(), virtv2.Resource(virtv2.VirtualMachineResource).String(), metav1.GetOptions{}) if err != nil { return nil, err } diff --git a/images/virtualization-artifact/pkg/common/cvmi/util.go b/images/virtualization-artifact/pkg/common/cvmi/util.go index 7d4dff6d3..048e1606c 100644 --- a/images/virtualization-artifact/pkg/common/cvmi/util.go +++ b/images/virtualization-artifact/pkg/common/cvmi/util.go @@ -6,13 +6,13 @@ import ( virtv2alpha1 "github.com/deckhouse/virtualization/api/core/v1alpha2" ) -// MakeOwnerReference makes owner reference from a ClusterVirtualMachineImage. -func MakeOwnerReference(cvmi *virtv2alpha1.ClusterVirtualMachineImage) metav1.OwnerReference { +// MakeOwnerReference makes owner reference from a ClusterVirtualImage. +func MakeOwnerReference(cvmi *virtv2alpha1.ClusterVirtualImage) metav1.OwnerReference { blockOwnerDeletion := true isController := true return metav1.OwnerReference{ - APIVersion: virtv2alpha1.ClusterVirtualMachineImageGVK.GroupVersion().String(), - Kind: virtv2alpha1.ClusterVirtualMachineImageGVK.Kind, + APIVersion: virtv2alpha1.ClusterVirtualImageGVK.GroupVersion().String(), + Kind: virtv2alpha1.ClusterVirtualImageGVK.Kind, Name: cvmi.Name, UID: cvmi.GetUID(), BlockOwnerDeletion: &blockOwnerDeletion, @@ -20,14 +20,6 @@ func MakeOwnerReference(cvmi *virtv2alpha1.ClusterVirtualMachineImage) metav1.Ow } } -func IsDVCRSource(cvmi *virtv2alpha1.ClusterVirtualMachineImage) bool { - if cvmi == nil { - return false - } - switch cvmi.Spec.DataSource.Type { - case virtv2alpha1.DataSourceTypeClusterVirtualMachineImage, - virtv2alpha1.DataSourceTypeVirtualMachineImage: - return true - } - return false +func IsDVCRSource(cvmi *virtv2alpha1.ClusterVirtualImage) bool { + return cvmi != nil && cvmi.Spec.DataSource.Type == virtv2alpha1.DataSourceTypeObjectRef } diff --git a/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go b/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go index 6fe41f24d..276c5231a 100644 --- a/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go +++ b/images/virtualization-artifact/pkg/common/datasource/ca_bundle.go @@ -8,7 +8,7 @@ type CABundle struct { ContainerImage *virtv2.DataSourceContainerRegistry } -func NewCABundleForCVMI(ds virtv2.CVMIDataSource) *CABundle { +func NewCABundleForCVMI(ds virtv2.ClusterVirtualImageDataSource) *CABundle { return &CABundle{ Type: ds.Type, HTTP: ds.HTTP, @@ -16,7 +16,7 @@ func NewCABundleForCVMI(ds virtv2.CVMIDataSource) *CABundle { } } -func NewCABundleForVMI(ds virtv2.VMIDataSource) *CABundle { +func NewCABundleForVMI(ds virtv2.VirtualImageDataSource) *CABundle { return &CABundle{ Type: ds.Type, HTTP: ds.HTTP, @@ -24,7 +24,7 @@ func NewCABundleForVMI(ds virtv2.VMIDataSource) *CABundle { } } -func NewCABundleForVMD(ds *virtv2.VMDDataSource) *CABundle { +func NewCABundleForVMD(ds *virtv2.VirtualDiskDataSource) *CABundle { return &CABundle{ Type: ds.Type, HTTP: ds.HTTP, diff --git a/images/virtualization-artifact/pkg/common/datavolume/size.go b/images/virtualization-artifact/pkg/common/datavolume/size.go index a8d2e2283..feba9f77b 100644 --- a/images/virtualization-artifact/pkg/common/datavolume/size.go +++ b/images/virtualization-artifact/pkg/common/datavolume/size.go @@ -8,7 +8,7 @@ import ( // // Virtualization-controller calculates unpacked size while importing image // into DVCR. This unpacked size is used to create PVC if size is not specified, -// i.e. VirtualMachineImage with storage: Kubernetes. +// i.e. VirtualImage with storage: Kubernetes. // The unpacked size is no enough, as CDI uses scratch PVC with Filesystem mode // to unpack disk image from dvcr image. // diff --git a/images/virtualization-artifact/pkg/common/vmd/util.go b/images/virtualization-artifact/pkg/common/vmd/util.go index de8230bd5..46e2511db 100644 --- a/images/virtualization-artifact/pkg/common/vmd/util.go +++ b/images/virtualization-artifact/pkg/common/vmd/util.go @@ -8,35 +8,31 @@ import ( virtv2alpha1 "github.com/deckhouse/virtualization/api/core/v1alpha2" ) -// MakeOwnerReference makes owner reference from a ClusterVirtualMachineImage. -func MakeOwnerReference(vmd *virtv2alpha1.VirtualMachineDisk) metav1.OwnerReference { +// MakeOwnerReference makes owner reference from a ClusterVirtualImage. +func MakeOwnerReference(vmd *virtv2alpha1.VirtualDisk) metav1.OwnerReference { return *metav1.NewControllerRef(vmd, schema.GroupVersionKind{ Group: virtvcore.GroupName, Version: virtv2alpha1.Version, - Kind: virtv2alpha1.VMDKind, + Kind: virtv2alpha1.VirtualDiskKind, }) } -func GetDataSourceType(vmd *virtv2alpha1.VirtualMachineDisk) string { +func GetDataSourceType(vmd *virtv2alpha1.VirtualDisk) string { if vmd == nil || vmd.Spec.DataSource == nil { return "" } return string(vmd.Spec.DataSource.Type) } -func IsDVCRSource(vmd *virtv2alpha1.VirtualMachineDisk) bool { +func IsDVCRSource(vmd *virtv2alpha1.VirtualDisk) bool { if vmd == nil || vmd.Spec.DataSource == nil { return false } - switch vmd.Spec.DataSource.Type { - case virtv2alpha1.DataSourceTypeClusterVirtualMachineImage, - virtv2alpha1.DataSourceTypeVirtualMachineImage: - return true - } - return false + + return vmd.Spec.DataSource.Type == virtv2alpha1.DataSourceTypeObjectRef } -func IsTwoPhaseImport(vmd *virtv2alpha1.VirtualMachineDisk) bool { +func IsTwoPhaseImport(vmd *virtv2alpha1.VirtualDisk) bool { if vmd == nil || vmd.Spec.DataSource == nil { return false } @@ -50,7 +46,7 @@ func IsTwoPhaseImport(vmd *virtv2alpha1.VirtualMachineDisk) bool { } // IsBlankPVC returns true if VMD has no DataSource: only PVC should be created. -func IsBlankPVC(vmd *virtv2alpha1.VirtualMachineDisk) bool { +func IsBlankPVC(vmd *virtv2alpha1.VirtualDisk) bool { if vmd == nil { return false } diff --git a/images/virtualization-artifact/pkg/common/vmi/util.go b/images/virtualization-artifact/pkg/common/vmi/util.go index feedc64bd..dee4b40b8 100644 --- a/images/virtualization-artifact/pkg/common/vmi/util.go +++ b/images/virtualization-artifact/pkg/common/vmi/util.go @@ -6,13 +6,13 @@ import ( virtv2alpha1 "github.com/deckhouse/virtualization/api/core/v1alpha2" ) -// MakeOwnerReference makes owner reference from a ClusterVirtualMachineImage. -func MakeOwnerReference(vmi *virtv2alpha1.VirtualMachineImage) metav1.OwnerReference { +// MakeOwnerReference makes owner reference from a ClusterVirtualImage. +func MakeOwnerReference(vmi *virtv2alpha1.VirtualImage) metav1.OwnerReference { blockOwnerDeletion := true isController := true return metav1.OwnerReference{ - APIVersion: virtv2alpha1.VirtualMachineImageGVK.GroupVersion().String(), - Kind: virtv2alpha1.VirtualMachineImageGVK.Kind, + APIVersion: virtv2alpha1.VirtualImageGVK.GroupVersion().String(), + Kind: virtv2alpha1.VirtualImageGVK.Kind, Name: vmi.Name, UID: vmi.GetUID(), BlockOwnerDeletion: &blockOwnerDeletion, @@ -20,29 +20,21 @@ func MakeOwnerReference(vmi *virtv2alpha1.VirtualMachineImage) metav1.OwnerRefer } } -func GetDataSourceType(vmi *virtv2alpha1.VirtualMachineImage) string { +func GetDataSourceType(vmi *virtv2alpha1.VirtualImage) string { if vmi == nil { return "" } return string(vmi.Spec.DataSource.Type) } -func IsDVCRSource(vmi *virtv2alpha1.VirtualMachineImage) bool { - if vmi == nil { - return false - } - switch vmi.Spec.DataSource.Type { - case virtv2alpha1.DataSourceTypeClusterVirtualMachineImage, - virtv2alpha1.DataSourceTypeVirtualMachineImage: - return true - } - return false +func IsDVCRSource(vmi *virtv2alpha1.VirtualImage) bool { + return vmi != nil && vmi.Spec.DataSource.Type == virtv2alpha1.DataSourceTypeObjectRef } // IsTwoPhaseImport returns true when two phase import is required: // 1. Import from dataSource to DVCR image using dvcr-importer or dvcr-uploader. // 2. Import DVCR image to PVC using DataVolume. -func IsTwoPhaseImport(vmi *virtv2alpha1.VirtualMachineImage) bool { +func IsTwoPhaseImport(vmi *virtv2alpha1.VirtualImage) bool { if vmi == nil { return false } diff --git a/images/virtualization-artifact/pkg/controller/common/util.go b/images/virtualization-artifact/pkg/controller/common/util.go index ca650bd73..4bae4aa58 100644 --- a/images/virtualization-artifact/pkg/controller/common/util.go +++ b/images/virtualization-artifact/pkg/controller/common/util.go @@ -307,11 +307,11 @@ func AddLabel(obj metav1.Object, key, value string) { } // PublishPodErr handles pod-creation errors and updates the CVMI without providing sensitive information. -// TODO make work with VirtualMachineImage object. +// TODO make work with VirtualImage object. func PublishPodErr(err error, podName string, obj client.Object, recorder record.EventRecorder, apiClient client.Client) error { // Generic reason and msg to avoid providing sensitive information reason := ErrStartingPod - msg := fmt.Sprintf(MessageErrStartingPod, podName) + msg := fmt.Sprintf(MessageErrStartingPod, podName) + ": " + err.Error() // Error handling to fine-tune the event with pertinent info if ErrQuotaExceeded(err) { diff --git a/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler.go b/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler.go index c09da9a40..76ea34bd3 100644 --- a/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler.go @@ -116,13 +116,13 @@ func (r *VMCPUReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, s } func (r *VMCPUReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { - return vm.Spec.CPU.ModelName != "" + return vm.Spec.CPU.VirtualMachineCPUModel != "" } func (r *VMCPUReconciler) EnqueueFromAttachedVM(vm *virtv2.VirtualMachine) []reconcile.Request { return []reconcile.Request{{ NamespacedName: types.NamespacedName{ - Name: vm.Spec.CPU.ModelName, + Name: vm.Spec.CPU.VirtualMachineCPUModel, }, }} } diff --git a/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler_state.go b/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler_state.go index 7bd4b9c90..7f74bf0a1 100644 --- a/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/cpu/cpu_reconciler_state.go @@ -107,7 +107,7 @@ func (state *VMCPUReconcilerState) IsAttachedToVM(vm virtv2.VirtualMachine) bool return false } - return state.VMCPU.Name().Name == vm.Spec.CPU.ModelName + return state.VMCPU.Name().Name == vm.Spec.CPU.VirtualMachineCPUModel } func (state *VMCPUReconcilerState) isDeletion() bool { diff --git a/images/virtualization-artifact/pkg/controller/cvmi_controller.go b/images/virtualization-artifact/pkg/controller/cvmi_controller.go index d17f263ef..abcd52e59 100644 --- a/images/virtualization-artifact/pkg/controller/cvmi_controller.go +++ b/images/virtualization-artifact/pkg/controller/cvmi_controller.go @@ -13,8 +13,8 @@ import ( ) const ( - cvmiControllerName = "cvmi-controller" - cvmiShortName = "cvmi" + cvmiControllerName = "cvi-controller" + cvmiShortName = "cvi" ImporterPodVerbose = "3" ImporterPodPullPolicy = string(corev1.PullIfNotPresent) @@ -55,6 +55,6 @@ func NewCVMIController( if err := reconciler.SetupController(ctx, mgr, cvmiController); err != nil { return nil, err } - log.Info("Initialized ClusterVirtualMachineImage controller", "image", importerImage, "namespace", controllerNamespace) + log.Info("Initialized ClusterVirtualImage controller", "image", importerImage, "namespace", controllerNamespace) return cvmiController, nil } diff --git a/images/virtualization-artifact/pkg/controller/cvmi_importer.go b/images/virtualization-artifact/pkg/controller/cvmi_importer.go index bf9bb048b..2f20ed30c 100644 --- a/images/virtualization-artifact/pkg/controller/cvmi_importer.go +++ b/images/virtualization-artifact/pkg/controller/cvmi_importer.go @@ -19,7 +19,7 @@ func (r *CVMIReconciler) startImporterPod( opts two_phase_reconciler.ReconcilerOptions, ) error { cvmi := state.CVMI.Current() - opts.Log.V(1).Info("Creating importer POD for CVMI", "cvmi.Name", cvmi.Name) + opts.Log.V(1).Info("Creating importer POD for CVI", "cvi.Name", cvmi.Name) importerSettings, err := r.createImporterSettings(state) if err != nil { @@ -64,20 +64,21 @@ func (r *CVMIReconciler) createImporterSettings(state *CVMIReconcilerState) (*im return nil, fmt.Errorf("dataSource '%s' specified without related 'containerImage' section", ds.Type) } importer.ApplyRegistrySourceSettings(settings, ds.ContainerImage, state.Supplements) - case virtv2alpha1.DataSourceTypeClusterVirtualMachineImage: - cvmiRef := ds.ClusterVirtualMachineImage - if cvmiRef == nil { - return nil, fmt.Errorf("dataSource '%s' specified without related 'clusterVirtualMachineImage' section", ds.Type) + case virtv2alpha1.DataSourceTypeObjectRef: + if ds.ObjectRef == nil { + return nil, fmt.Errorf("dataSource '%s' specified without related 'objectRef' section", ds.Type) } - dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(cvmiRef.Name) - importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) - case virtv2alpha1.DataSourceTypeVirtualMachineImage: - vmiRef := ds.VirtualMachineImage - if vmiRef == nil { - return nil, fmt.Errorf("dataSource '%s' specified without related 'virtualMachineImage' section", ds.Type) + + switch ds.ObjectRef.Kind { + case virtv2alpha1.ClusterVirtualImageObjectRefKindVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(ds.ObjectRef.Name, ds.ObjectRef.Namespace) + importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) + case virtv2alpha1.ClusterVirtualImageObjectRefKindClusterVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ObjectRef.Name) + importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) + default: + return nil, fmt.Errorf("unknown objectRef kind: %s", ds.ObjectRef.Kind) } - dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(vmiRef.Name, vmiRef.Namespace) - importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) default: return nil, fmt.Errorf("unknown dataSource: %s", ds.Type) } @@ -100,6 +101,6 @@ func (r *CVMIReconciler) createImporterPodSettings(state *CVMIReconcilerState) * Namespace: importerPod.Namespace, OwnerReference: cvmiutil.MakeOwnerReference(state.CVMI.Current()), ControllerName: cvmiControllerName, - InstallerLabels: r.installerLabels, + InstallerLabels: map[string]string{}, } } diff --git a/images/virtualization-artifact/pkg/controller/cvmi_reconciler.go b/images/virtualization-artifact/pkg/controller/cvmi_reconciler.go index ba1ce77b0..1e6df4e18 100644 --- a/images/virtualization-artifact/pkg/controller/cvmi_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/cvmi_reconciler.go @@ -32,14 +32,13 @@ import ( ) type CVMIReconciler struct { - *vmattachee.AttacheeReconciler[*virtv2.ClusterVirtualMachineImage, virtv2.ClusterVirtualMachineImageStatus] - - importerImage string - uploaderImage string - verbose string - pullPolicy string - installerLabels map[string]string - dvcrSettings *dvcr.Settings + *vmattachee.AttacheeReconciler[*virtv2.ClusterVirtualImage, virtv2.ClusterVirtualImageStatus] + + importerImage string + uploaderImage string + verbose string + pullPolicy string + dvcrSettings *dvcr.Settings } func NewCVMIReconciler(importerImage, uploaderImage, verbose, pullPolicy string, dvcrSettings *dvcr.Settings) *CVMIReconciler { @@ -50,15 +49,15 @@ func NewCVMIReconciler(importerImage, uploaderImage, verbose, pullPolicy string, pullPolicy: pullPolicy, dvcrSettings: dvcrSettings, AttacheeReconciler: vmattachee.NewAttacheeReconciler[ - *virtv2.ClusterVirtualMachineImage, - virtv2.ClusterVirtualMachineImageStatus, + *virtv2.ClusterVirtualImage, + virtv2.ClusterVirtualImageStatus, ](), } } func (r *CVMIReconciler) SetupController(ctx context.Context, mgr manager.Manager, ctr controller.Controller) error { if err := ctr.Watch( - source.Kind(mgr.GetCache(), &virtv2.ClusterVirtualMachineImage{}), + source.Kind(mgr.GetCache(), &virtv2.ClusterVirtualImage{}), &handler.EnqueueRequestForObject{}, predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { return true }, @@ -74,7 +73,7 @@ func (r *CVMIReconciler) SetupController(ctx context.Context, mgr manager.Manage // Sync creates and deletes importer Pod depending on CVMI status. func (r *CVMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *CVMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.Info("Reconcile required for CVMI", "cvmi.name", state.CVMI.Current().Name, "cvmi.phase", state.CVMI.Current().Status.Phase) + opts.Log.Info("Reconcile required for CVI", "cvi.name", state.CVMI.Current().Name, "cvi.phase", state.CVMI.Current().Status.Phase) if r.AttacheeReconciler.Sync(ctx, state.AttacheeState, opts) { return nil @@ -83,7 +82,7 @@ func (r *CVMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *C // Change the world depending on states of CVMI and Pod. switch { case state.IsDeletion(): - opts.Log.V(1).Info("Delete CVMI, remove protective finalizers") + opts.Log.V(1).Info("Delete CVI, remove protective finalizers") return r.cleanupOnDeletion(ctx, state, opts) case !state.IsProtected(): if err := r.verifyDataSourceRefs(ctx, opts.Client, state); err != nil { @@ -103,7 +102,7 @@ func (r *CVMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *C } return nil case state.IsFailed(): - opts.Log.Info("VMI failed: cleanup underlying resources") + opts.Log.Info("CVI failed: cleanup underlying resources") // Delete underlying importer/uploader Pod, Service and DataVolume and stop the reconcile process. if cc.ShouldCleanupSubResources(state.CVMI.Current()) { return r.cleanup(ctx, state.CVMI.Changed(), opts.Client, state) @@ -111,7 +110,7 @@ func (r *CVMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *C return nil case state.CanStartPod(): // Create Pod using name and namespace from annotation. - opts.Log.V(1).Info("Pod for CVMI not found, create new one") + opts.Log.V(1).Info("Pod for CVI not found, create new one") if cvmiutil.IsDVCRSource(state.CVMI.Current()) && !state.DVCRDataSource.IsReady() { opts.Log.V(1).Info("Wait for the data source to be ready") @@ -128,7 +127,7 @@ func (r *CVMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *C return nil case state.IsImportInProgress(), state.IsImportInPending(): // Import is in progress, force a re-reconcile in 2 seconds to update status. - opts.Log.V(2).Info("Requeue: CVMI import is in progress", "cvmi.name", state.CVMI.Current().Name) + opts.Log.V(2).Info("Requeue: CVI import is in progress", "cvi.name", state.CVMI.Current().Name) if err := r.ensurePodFinalizers(ctx, state, opts); err != nil { return err } @@ -137,17 +136,17 @@ func (r *CVMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *C } // Report unexpected state. - details := fmt.Sprintf("cvmi.Status.Phase='%s'", state.CVMI.Current().Status.Phase) + details := fmt.Sprintf("cvi.Status.Phase='%s'", state.CVMI.Current().Status.Phase) if state.Pod != nil { details += fmt.Sprintf(" pod.Name='%s' pod.Status.Phase='%s'", state.Pod.Name, state.Pod.Status.Phase) } - opts.Recorder.Event(state.CVMI.Current(), corev1.EventTypeWarning, virtv2.ReasonErrUnknownState, fmt.Sprintf("CVMI has unexpected state, recreate it to start import again. %s", details)) + opts.Recorder.Event(state.CVMI.Current(), corev1.EventTypeWarning, virtv2.ReasonErrUnknownState, fmt.Sprintf("CVI has unexpected state, recreate it to start import again. %s", details)) return nil } func (r *CVMIReconciler) UpdateStatus(ctx context.Context, _ reconcile.Request, state *CVMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(2).Info("Update CVMI status") + opts.Log.V(2).Info("Update CVI status") // Record event if Pod has error. // TODO set Failed status if Pod restarts are greater than some threshold? @@ -179,10 +178,9 @@ func (r *CVMIReconciler) UpdateStatus(ctx context.Context, _ reconcile.Request, break case !state.IsPodComplete(): // Set CVMI status to Provisioning and copy progress metrics from importer/uploader Pod. - opts.Log.V(2).Info("Fetch progress", "cvmi.name", state.CVMI.Current().Name) + opts.Log.V(2).Info("Fetch progress", "cvi.name", state.CVMI.Current().Name) cvmiStatus.Phase = virtv2.ImageProvisioning - t := state.CVMI.Current().Spec.DataSource.Type - if t == virtv2.DataSourceTypeUpload && + if state.CVMI.Current().Spec.DataSource.Type == virtv2.DataSourceTypeUpload && cvmiStatus.UploadCommand == "" && state.Ingress != nil && state.Ingress.GetAnnotations()[cc.AnnUploadURL] != "" { @@ -200,7 +198,7 @@ func (r *CVMIReconciler) UpdateStatus(ctx context.Context, _ reconcile.Request, return err } if progress != nil { - opts.Log.V(2).Info("Got progress", "cvmi.name", state.CVMI.Current().Name, "progress", progress.Progress(), "speed", progress.AvgSpeed(), "progress.raw", progress.ProgressRaw(), "speed.raw", progress.AvgSpeedRaw()) + opts.Log.V(2).Info("Got progress", "cvi.name", state.CVMI.Current().Name, "progress", progress.Progress(), "speed", progress.AvgSpeed(), "progress.raw", progress.ProgressRaw(), "speed.raw", progress.AvgSpeedRaw()) cvmiStatus.Progress = progress.Progress() cvmiStatus.DownloadSpeed.Avg = progress.AvgSpeed() cvmiStatus.DownloadSpeed.AvgBytes = strconv.FormatUint(progress.AvgSpeedRaw(), 10) @@ -211,7 +209,7 @@ func (r *CVMIReconciler) UpdateStatus(ctx context.Context, _ reconcile.Request, // Set CVMI phase. if state.CVMI.Current().Spec.DataSource.Type == virtv2.DataSourceTypeUpload && (progress == nil || progress.ProgressRaw() == 0) { cvmiStatus.Phase = virtv2.ImageWaitForUserUpload - if helper.GetAge(state.Pod) > cc.UploaderWaitDuration { + if state.Pod != nil && helper.GetAge(state.Pod) > cc.UploaderWaitDuration { cvmiStatus.Phase = virtv2.ImageFailed cvmiStatus.FailureReason = virtv2.ReasonErrUploaderWaitDurationExpired cvmiStatus.FailureMessage = "uploading time expired" @@ -267,7 +265,7 @@ func (r *CVMIReconciler) UpdateStatus(ctx context.Context, _ reconcile.Request, func (r *CVMIReconciler) verifyDataSourceRefs(ctx context.Context, client client.Client, state *CVMIReconcilerState) error { cvmi := state.CVMI.Current() switch cvmi.Spec.DataSource.Type { - case virtv2.DataSourceTypeClusterVirtualMachineImage, virtv2.DataSourceTypeVirtualMachineImage: + case virtv2.DataSourceTypeObjectRef: if err := state.DVCRDataSource.Validate(); err != nil { return err } @@ -293,7 +291,7 @@ func (r *CVMIReconciler) verifyDataSourceRefs(ctx context.Context, client client return nil } -func (r *CVMIReconciler) cleanup(ctx context.Context, cvmi *virtv2.ClusterVirtualMachineImage, client client.Client, state *CVMIReconcilerState) error { +func (r *CVMIReconciler) cleanup(ctx context.Context, cvmi *virtv2.ClusterVirtualImage, client client.Client, state *CVMIReconcilerState) error { switch cvmi.Spec.DataSource.Type { case virtv2.DataSourceTypeUpload: if state.Ingress != nil { @@ -385,8 +383,8 @@ func (r *CVMIReconciler) cleanupOnDeletion(ctx context.Context, state *CVMIRecon } func (r *CVMIReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type == virtv2.ClusterImageDevice && bda.ClusterVirtualMachineImage != nil { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.ClusterImageDevice { return true } } @@ -397,13 +395,13 @@ func (r *CVMIReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { func (r *CVMIReconciler) EnqueueFromAttachedVM(vm *virtv2.VirtualMachine) []reconcile.Request { var requests []reconcile.Request - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type != virtv2.ClusterImageDevice || bda.ClusterVirtualMachineImage == nil { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind != virtv2.ClusterImageDevice { continue } requests = append(requests, reconcile.Request{NamespacedName: types.NamespacedName{ - Name: bda.ClusterVirtualMachineImage.Name, + Name: bda.Name, }}) } diff --git a/images/virtualization-artifact/pkg/controller/cvmi_reconciler_state.go b/images/virtualization-artifact/pkg/controller/cvmi_reconciler_state.go index e914e0a59..f6a7d0ce9 100644 --- a/images/virtualization-artifact/pkg/controller/cvmi_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/cvmi_reconciler_state.go @@ -23,14 +23,14 @@ import ( ) type CVMIReconcilerState struct { - *vmattachee.AttacheeState[*virtv2.ClusterVirtualMachineImage, virtv2.ClusterVirtualMachineImageStatus] + *vmattachee.AttacheeState[*virtv2.ClusterVirtualImage, virtv2.ClusterVirtualImageStatus] Client client.Client Supplements *supplements.Generator Result *reconcile.Result Namespace string - CVMI *helper.Resource[*virtv2.ClusterVirtualMachineImage, virtv2.ClusterVirtualMachineImageStatus] + CVMI *helper.Resource[*virtv2.ClusterVirtualImage, virtv2.ClusterVirtualImageStatus] Service *corev1.Service Ingress *netv1.Ingress Pod *corev1.Pod @@ -43,8 +43,8 @@ func NewCVMIReconcilerState(controllerNamespace string) func(name types.Namespac Client: client, CVMI: helper.NewResource( name, log, client, cache, - func() *virtv2.ClusterVirtualMachineImage { return &virtv2.ClusterVirtualMachineImage{} }, - func(obj *virtv2.ClusterVirtualMachineImage) virtv2.ClusterVirtualMachineImageStatus { + func() *virtv2.ClusterVirtualImage { return &virtv2.ClusterVirtualImage{} }, + func(obj *virtv2.ClusterVirtualImage) virtv2.ClusterVirtualImageStatus { return obj.Status }, ), @@ -61,7 +61,7 @@ func NewCVMIReconcilerState(controllerNamespace string) func(name types.Namespac func (state *CVMIReconcilerState) ApplySync(ctx context.Context, _ logr.Logger) error { if err := state.CVMI.UpdateMeta(ctx); err != nil { - return fmt.Errorf("unable to update CVMI %q meta: %w", state.CVMI.Name(), err) + return fmt.Errorf("unable to update CVI %q meta: %w", state.CVMI.Name(), err) } return nil } @@ -84,7 +84,7 @@ func (state *CVMIReconcilerState) Reload(ctx context.Context, req reconcile.Requ return fmt.Errorf("unable to get %q: %w", req.NamespacedName, err) } if state.CVMI.IsEmpty() { - log.Info("Reconcile observe an absent CVMI: it may be deleted", "CVMI", req.NamespacedName) + log.Info("Reconcile observe an absent CVI: it may be deleted", "cvi", req.NamespacedName) return nil } @@ -95,9 +95,9 @@ func (state *CVMIReconcilerState) Reload(ctx context.Context, req reconcile.Requ UID: state.CVMI.Current().UID, } - t := state.CVMI.Current().Spec.DataSource.Type + ds := state.CVMI.Current().Spec.DataSource - switch t { + switch ds.Type { case virtv2.DataSourceTypeUpload: state.Pod, err = uploader.FindPod(ctx, client, state.Supplements) if err != nil { @@ -118,11 +118,8 @@ func (state *CVMIReconcilerState) Reload(ctx context.Context, req reconcile.Requ if err != nil { return err } - } - // TODO These resources are not part of the state. Retrieve additional resources in Sync phase. - switch t { - case virtv2.DataSourceTypeClusterVirtualMachineImage, virtv2.DataSourceTypeVirtualMachineImage: + // TODO These resources are not part of the state. Retrieve additional resources in Sync phase. state.DVCRDataSource, err = NewDVCRDataSourcesForCVMI(ctx, state.CVMI.Current().Spec.DataSource, client) if err != nil { return err @@ -173,7 +170,7 @@ func (state *CVMIReconcilerState) IsImportInPending() bool { // CanStartPod returns whether importer Pod can be started. // NOTE: valid only if ShouldTrackPod is true. func (state *CVMIReconcilerState) CanStartPod() bool { - return state.Pod == nil && !state.IsReady() + return !state.IsReady() && !state.IsFailed() && state.Pod == nil } func (state *CVMIReconcilerState) IsReady() bool { @@ -194,8 +191,8 @@ func (state *CVMIReconcilerState) IsAttachedToVM(vm virtv2.VirtualMachine) bool return false } - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type == virtv2.ClusterImageDevice && bda.ClusterVirtualMachineImage != nil && bda.ClusterVirtualMachineImage.Name == state.CVMI.Name().Name { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.ClusterImageDevice && bda.Name == state.CVMI.Name().Name { return true } } diff --git a/images/virtualization-artifact/pkg/controller/cvmi_uploader.go b/images/virtualization-artifact/pkg/controller/cvmi_uploader.go index 43a5ac625..55ad70558 100644 --- a/images/virtualization-artifact/pkg/controller/cvmi_uploader.go +++ b/images/virtualization-artifact/pkg/controller/cvmi_uploader.go @@ -14,7 +14,7 @@ import ( func (r *CVMIReconciler) startUploaderPod(ctx context.Context, state *CVMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { cvmi := state.CVMI.Current() - opts.Log.V(1).Info("Creating uploader POD for CVMI", "cvmi.Name", cvmi.Name) + opts.Log.V(1).Info("Creating uploader POD for CVI", "cvi.Name", cvmi.Name) uploaderSettings := r.createUploaderSettings(state) @@ -61,13 +61,13 @@ func (r *CVMIReconciler) createUploaderPodSettings(state *CVMIReconcilerState) * Namespace: uploaderPod.Namespace, OwnerReference: cvmiutil.MakeOwnerReference(state.CVMI.Current()), ControllerName: cvmiControllerName, - InstallerLabels: r.installerLabels, + InstallerLabels: map[string]string{}, ServiceName: uploaderSvc.Name, } } func (r *CVMIReconciler) startUploaderService(ctx context.Context, state *CVMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(1).Info("Creating uploader Service for CVMI", "cvmi.Name", state.CVMI.Current().Name) + opts.Log.V(1).Info("Creating uploader Service for CVI", "cvi.Name", state.CVMI.Current().Name) uploaderService := uploader.NewService(r.createUploaderServiceSettings(state)) @@ -91,7 +91,7 @@ func (r *CVMIReconciler) createUploaderServiceSettings(state *CVMIReconcilerStat } func (r *CVMIReconciler) startUploaderIngress(ctx context.Context, state *CVMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(1).Info("Creating uploader Ingress for CVMI", "cvmi.Name", state.CVMI.Current().Name) + opts.Log.V(1).Info("Creating uploader Ingress for CVI", "cvi.Name", state.CVMI.Current().Name) uploaderIng := uploader.NewIngress(r.createUploaderIngressSettings(state)) diff --git a/images/virtualization-artifact/pkg/controller/dvcr_data_source.go b/images/virtualization-artifact/pkg/controller/dvcr_data_source.go index 282163dda..d0921fe31 100644 --- a/images/virtualization-artifact/pkg/controller/dvcr_data_source.go +++ b/images/virtualization-artifact/pkg/controller/dvcr_data_source.go @@ -21,15 +21,19 @@ type DVCRDataSource struct { isReady bool } -func NewDVCRDataSourcesForCVMI(ctx context.Context, ds virtv2.CVMIDataSource, client client.Client) (*DVCRDataSource, error) { +func NewDVCRDataSourcesForCVMI(ctx context.Context, ds virtv2.ClusterVirtualImageDataSource, client client.Client) (*DVCRDataSource, error) { + if ds.ObjectRef == nil { + return nil, nil + } + var dsDVCR DVCRDataSource - switch ds.Type { - case virtv2.DataSourceTypeVirtualMachineImage: - vmiName := ds.VirtualMachineImage.Name - vmiNS := ds.VirtualMachineImage.Namespace + switch ds.ObjectRef.Kind { + case virtv2.ClusterVirtualImageObjectRefKindVirtualImage: + vmiName := ds.ObjectRef.Name + vmiNS := ds.ObjectRef.Namespace if vmiName != "" && vmiNS != "" { - vmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmiName, Namespace: vmiNS}, client, &virtv2.VirtualMachineImage{}) + vmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmiName, Namespace: vmiNS}, client, &virtv2.VirtualImage{}) if err != nil { return nil, err } @@ -41,10 +45,10 @@ func NewDVCRDataSourcesForCVMI(ctx context.Context, ds virtv2.CVMIDataSource, cl dsDVCR.isReady = vmi.Status.Phase == virtv2.ImageReady } } - case virtv2.DataSourceTypeClusterVirtualMachineImage: - cvmiName := ds.ClusterVirtualMachineImage.Name + case virtv2.ClusterVirtualImageObjectRefKindClusterVirtualImage: + cvmiName := ds.ObjectRef.Name if cvmiName != "" { - cvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: cvmiName}, client, &virtv2.ClusterVirtualMachineImage{}) + cvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: cvmiName}, client, &virtv2.ClusterVirtualImage{}) if err != nil { return nil, err } @@ -61,15 +65,19 @@ func NewDVCRDataSourcesForCVMI(ctx context.Context, ds virtv2.CVMIDataSource, cl return &dsDVCR, nil } -func NewDVCRDataSourcesForVMI(ctx context.Context, ds virtv2.VMIDataSource, obj metav1.Object, client client.Client) (*DVCRDataSource, error) { +func NewDVCRDataSourcesForVMI(ctx context.Context, ds virtv2.VirtualImageDataSource, obj metav1.Object, client client.Client) (*DVCRDataSource, error) { + if ds.ObjectRef == nil { + return nil, nil + } + var dsDVCR DVCRDataSource - switch ds.Type { - case virtv2.DataSourceTypeVirtualMachineImage: - vmiName := ds.VirtualMachineImage.Name + switch ds.ObjectRef.Kind { + case virtv2.VirtualImageObjectRefKindVirtualImage: + vmiName := ds.ObjectRef.Name vmiNS := obj.GetNamespace() if vmiName != "" && vmiNS != "" { - vmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmiName, Namespace: vmiNS}, client, &virtv2.VirtualMachineImage{}) + vmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmiName, Namespace: vmiNS}, client, &virtv2.VirtualImage{}) if err != nil { return nil, err } @@ -81,10 +89,10 @@ func NewDVCRDataSourcesForVMI(ctx context.Context, ds virtv2.VMIDataSource, obj dsDVCR.isReady = vmi.Status.Phase == virtv2.ImageReady } } - case virtv2.DataSourceTypeClusterVirtualMachineImage: - cvmiName := ds.ClusterVirtualMachineImage.Name + case virtv2.VirtualImageObjectRefKindClusterVirtualImage: + cvmiName := ds.ObjectRef.Name if cvmiName != "" { - cvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: cvmiName}, client, &virtv2.ClusterVirtualMachineImage{}) + cvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: cvmiName}, client, &virtv2.ClusterVirtualImage{}) if err != nil { return nil, err } @@ -101,19 +109,19 @@ func NewDVCRDataSourcesForVMI(ctx context.Context, ds virtv2.VMIDataSource, obj return &dsDVCR, nil } -func NewDVCRDataSourcesForVMD(ctx context.Context, ds *virtv2.VMDDataSource, obj metav1.Object, client client.Client) (*DVCRDataSource, error) { - if ds == nil { +func NewDVCRDataSourcesForVMD(ctx context.Context, ds *virtv2.VirtualDiskDataSource, obj metav1.Object, client client.Client) (*DVCRDataSource, error) { + if ds == nil || ds.ObjectRef == nil { return nil, nil } var dsDVCR DVCRDataSource - switch ds.Type { - case virtv2.DataSourceTypeVirtualMachineImage: - vmiName := ds.VirtualMachineImage.Name + switch ds.ObjectRef.Kind { + case virtv2.VirtualDiskObjectRefKindVirtualImage: + vmiName := ds.ObjectRef.Name vmiNS := obj.GetNamespace() if vmiName != "" && vmiNS != "" { - vmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmiName, Namespace: vmiNS}, client, &virtv2.VirtualMachineImage{}) + vmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmiName, Namespace: vmiNS}, client, &virtv2.VirtualImage{}) if err != nil { return nil, err } @@ -126,10 +134,10 @@ func NewDVCRDataSourcesForVMD(ctx context.Context, ds *virtv2.VMDDataSource, obj dsDVCR.isReady = vmi.Status.Phase == virtv2.ImageReady } } - case virtv2.DataSourceTypeClusterVirtualMachineImage: - cvmiName := ds.ClusterVirtualMachineImage.Name + case virtv2.VirtualDiskObjectRefKindClusterVirtualImage: + cvmiName := ds.ObjectRef.Name if cvmiName != "" { - cvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: cvmiName}, client, &virtv2.ClusterVirtualMachineImage{}) + cvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: cvmiName}, client, &virtv2.ClusterVirtualImage{}) if err != nil { return nil, err } diff --git a/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler.go b/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler.go index 66f376c1d..6b29f900c 100644 --- a/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler.go @@ -81,7 +81,7 @@ func (r *ClaimReconciler) enqueueRequestsFromVMs(_ context.Context, obj client.O return nil } - if vm.Spec.VirtualMachineIPAddressClaimName == "" { + if vm.Spec.VirtualMachineIPAddressClaim == "" { return []reconcile.Request{ { NamespacedName: types.NamespacedName{ @@ -96,7 +96,7 @@ func (r *ClaimReconciler) enqueueRequestsFromVMs(_ context.Context, obj client.O { NamespacedName: types.NamespacedName{ Namespace: vm.Namespace, - Name: vm.Spec.VirtualMachineIPAddressClaimName, + Name: vm.Spec.VirtualMachineIPAddressClaim, }, }, } @@ -139,15 +139,15 @@ func (r *ClaimReconciler) Sync(ctx context.Context, _ reconcile.Request, state * } switch { - case state.Lease == nil && state.Claim.Current().Spec.LeaseName != "": + case state.Lease == nil && state.Claim.Current().Spec.VirtualMachineIPAddressLease != "": opts.Log.Info("Lease by name not found: waiting for the lease to be available") return nil case state.Lease == nil: - // Lease not found by spec.LeaseName or spec.Address: it doesn't exist. - opts.Log.Info("No Lease for Claim: create the new one", "address", state.Claim.Current().Spec.Address, "leaseName", state.Claim.Current().Spec.LeaseName) + // Lease not found by spec.virtualMachineIPAddressLease or spec.Address: it doesn't exist. + opts.Log.Info("No Lease for Claim: create the new one", "address", state.Claim.Current().Spec.Address, "leaseName", state.Claim.Current().Spec.VirtualMachineIPAddressLease) - leaseName := state.Claim.Current().Spec.LeaseName + leaseName := state.Claim.Current().Spec.VirtualMachineIPAddressLease if state.Claim.Current().Spec.Address == "" { if leaseName != "" { @@ -195,7 +195,7 @@ func (r *ClaimReconciler) Sync(ctx context.Context, _ reconcile.Request, state * return err } - state.Claim.Changed().Spec.LeaseName = leaseName + state.Claim.Changed().Spec.VirtualMachineIPAddressLease = leaseName err = opts.Client.Update(ctx, state.Claim.Changed()) if err != nil { @@ -231,7 +231,7 @@ func (r *ClaimReconciler) Sync(ctx context.Context, _ reconcile.Request, state * return err } - state.Claim.Changed().Spec.LeaseName = state.Lease.Name + state.Claim.Changed().Spec.VirtualMachineIPAddressLease = state.Lease.Name state.Claim.Changed().Spec.Address = leaseNameToIP(state.Lease.Name) return opts.Client.Update(ctx, state.Claim.Changed()) @@ -246,16 +246,16 @@ func (r *ClaimReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, s claimStatus := state.Claim.Current().Status.DeepCopy() - claimStatus.VMName = "" + claimStatus.VirtualMachine = "" if state.VM != nil { - claimStatus.VMName = state.VM.Name + claimStatus.VirtualMachine = state.VM.Name } claimStatus.Address = "" claimStatus.ConflictMessage = "" switch { - case state.Lease == nil && state.Claim.Current().Spec.LeaseName != "": + case state.Lease == nil && state.Claim.Current().Spec.VirtualMachineIPAddressLease != "": claimStatus.Phase = virtv2.VirtualMachineIPAddressClaimPhaseLost case state.Lease == nil: diff --git a/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler_state.go b/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler_state.go index cc7309af9..a9760d5ff 100644 --- a/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/ipam/claim_reconciler_state.go @@ -72,8 +72,8 @@ func (state *ClaimReconcilerState) Reload(ctx context.Context, req reconcile.Req return nil } - if state.Claim.Current().Status.VMName != "" { - vmKey := types.NamespacedName{Name: state.Claim.Current().Status.VMName, Namespace: state.Claim.Name().Namespace} + if state.Claim.Current().Status.VirtualMachine != "" { + vmKey := types.NamespacedName{Name: state.Claim.Current().Status.VirtualMachine, Namespace: state.Claim.Name().Namespace} state.VM, err = helper.FetchObject(ctx, vmKey, apiClient, &virtv2.VirtualMachine{}) if err != nil { return fmt.Errorf("unable to get VM %s: %w", vmKey, err) @@ -90,8 +90,8 @@ func (state *ClaimReconcilerState) Reload(ctx context.Context, req reconcile.Req } for _, vm := range vms.Items { - if vm.Spec.VirtualMachineIPAddressClaimName == state.Claim.Name().Name || - vm.Spec.VirtualMachineIPAddressClaimName == "" && vm.Name == state.Claim.Name().Name { + if vm.Spec.VirtualMachineIPAddressClaim == state.Claim.Name().Name || + vm.Spec.VirtualMachineIPAddressClaim == "" && vm.Name == state.Claim.Name().Name { state.VM = new(virtv2.VirtualMachine) *state.VM = vm break @@ -99,7 +99,7 @@ func (state *ClaimReconcilerState) Reload(ctx context.Context, req reconcile.Req } } - leaseName := state.Claim.Current().Spec.LeaseName + leaseName := state.Claim.Current().Spec.VirtualMachineIPAddressLease if leaseName == "" { leaseName = ipToLeaseName(state.Claim.Current().Spec.Address) } diff --git a/images/virtualization-artifact/pkg/controller/ipam/claim_webhook.go b/images/virtualization-artifact/pkg/controller/ipam/claim_webhook.go index db0470bcf..272231684 100644 --- a/images/virtualization-artifact/pkg/controller/ipam/claim_webhook.go +++ b/images/virtualization-artifact/pkg/controller/ipam/claim_webhook.go @@ -28,7 +28,7 @@ func (v *ClaimValidator) ValidateCreate(ctx context.Context, obj runtime.Object) return nil, fmt.Errorf("expected a new VirtualMachineIPAddressClaim but got a %T", obj) } - v.log.Info("Validate Claim creating", "name", claim.Name, "address", claim.Spec.Address, "leaseName", claim.Spec.LeaseName) + v.log.Info("Validate Claim creating", "name", claim.Name, "address", claim.Spec.Address, "leaseName", claim.Spec.VirtualMachineIPAddressLease) err := v.validateSpecFields(claim.Spec) if err != nil { @@ -37,7 +37,7 @@ func (v *ClaimValidator) ValidateCreate(ctx context.Context, obj runtime.Object) ip := claim.Spec.Address if ip == "" { - ip = leaseNameToIP(claim.Spec.LeaseName) + ip = leaseNameToIP(claim.Spec.VirtualMachineIPAddressLease) } if ip != "" { @@ -68,14 +68,14 @@ func (v *ClaimValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtim v.log.Info("Validate Claim updating", "name", newClaim.Name, "old.address", oldClaim.Spec.Address, "new.address", newClaim.Spec.Address, - "old.leaseName", oldClaim.Spec.LeaseName, "new.leaseName", newClaim.Spec.LeaseName, + "old.leaseName", oldClaim.Spec.VirtualMachineIPAddressLease, "new.leaseName", newClaim.Spec.VirtualMachineIPAddressLease, ) if oldClaim.Spec.Address != "" && oldClaim.Spec.Address != newClaim.Spec.Address { return nil, errors.New("the claim address cannot be changed if allocated") } - if oldClaim.Spec.LeaseName != "" && oldClaim.Spec.LeaseName != newClaim.Spec.LeaseName { + if oldClaim.Spec.VirtualMachineIPAddressLease != "" && oldClaim.Spec.VirtualMachineIPAddressLease != newClaim.Spec.VirtualMachineIPAddressLease { return nil, errors.New("the lease name cannot be changed if allocated") } @@ -94,7 +94,7 @@ func (v *ClaimValidator) ValidateDelete(_ context.Context, _ runtime.Object) (ad } func (v *ClaimValidator) validateSpecFields(spec v1alpha2.VirtualMachineIPAddressClaimSpec) error { - if spec.LeaseName != "" && !isValidAddressFormat(leaseNameToIP(spec.LeaseName)) { + if spec.VirtualMachineIPAddressLease != "" && !isValidAddressFormat(leaseNameToIP(spec.VirtualMachineIPAddressLease)) { return errors.New("the lease name is not created from a valid IP address or ip prefix is missing") } @@ -102,7 +102,7 @@ func (v *ClaimValidator) validateSpecFields(spec v1alpha2.VirtualMachineIPAddres return errors.New("the claim address is not a valid textual representation of an IP address") } - if spec.Address != "" && spec.LeaseName != "" && spec.Address != leaseNameToIP(spec.LeaseName) { + if spec.Address != "" && spec.VirtualMachineIPAddressLease != "" && spec.Address != leaseNameToIP(spec.VirtualMachineIPAddressLease) { return errors.New("lease name doesn't match the address") } diff --git a/images/virtualization-artifact/pkg/controller/ipam/ipam.go b/images/virtualization-artifact/pkg/controller/ipam/ipam.go index 9538317ba..6ddc21ecc 100644 --- a/images/virtualization-artifact/pkg/controller/ipam/ipam.go +++ b/images/virtualization-artifact/pkg/controller/ipam/ipam.go @@ -29,7 +29,7 @@ func (m IPAM) IsBound(vmName string, claim *virtv2.VirtualMachineIPAddressClaim) return false } - return claim.Status.VMName == vmName + return claim.Status.VirtualMachine == vmName } func (m IPAM) CheckClaimAvailableForBinding(vmName string, claim *virtv2.VirtualMachineIPAddressClaim) error { @@ -37,7 +37,7 @@ func (m IPAM) CheckClaimAvailableForBinding(vmName string, claim *virtv2.Virtual return errors.New("cannot to bind with empty claim") } - boundVMName := claim.Status.VMName + boundVMName := claim.Status.VirtualMachine if boundVMName == "" || boundVMName == vmName { return nil } diff --git a/images/virtualization-artifact/pkg/controller/ipam/lease_reconciler.go b/images/virtualization-artifact/pkg/controller/ipam/lease_reconciler.go index 4f440b1fb..1e4331a8d 100644 --- a/images/virtualization-artifact/pkg/controller/ipam/lease_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/ipam/lease_reconciler.go @@ -47,14 +47,14 @@ func (r *LeaseReconciler) enqueueRequestsFromClaims(_ context.Context, obj clien return nil } - if claim.Spec.LeaseName == "" { + if claim.Spec.VirtualMachineIPAddressLease == "" { return nil } return []reconcile.Request{ { NamespacedName: types.NamespacedName{ - Name: claim.Spec.LeaseName, + Name: claim.Spec.VirtualMachineIPAddressLease, }, }, } diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index 3a62c923e..706cc2da0 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -255,17 +255,39 @@ func (b *KVVM) SetDisk(name string, opts SetDiskOptions) error { case opts.Provisioning != nil: switch opts.Provisioning.Type { - case virtv2.ProvisioningTypeSysprepSecret: - vs.Sysprep = &virtv1.SysprepSource{ - Secret: opts.Provisioning.SysprepSecretRef, + case virtv2.ProvisioningTypeSysprepRef: + if opts.Provisioning.SysprepRef == nil { + return fmt.Errorf("nil sysprep ref: %s", opts.Provisioning.Type) + } + + switch opts.Provisioning.SysprepRef.Kind { + case virtv2.SysprepRefKindSecret: + vs.Sysprep = &virtv1.SysprepSource{ + Secret: &corev1.LocalObjectReference{ + Name: opts.Provisioning.SysprepRef.Name, + }, + } + default: + return fmt.Errorf("unexpected sysprep ref kind: %s", opts.Provisioning.SysprepRef.Kind) } case virtv2.ProvisioningTypeUserData: vs.CloudInitNoCloud = &virtv1.CloudInitNoCloudSource{ UserData: opts.Provisioning.UserData, } - case virtv2.ProvisioningTypeUserDataSecret: - vs.CloudInitNoCloud = &virtv1.CloudInitNoCloudSource{ - UserDataSecretRef: opts.Provisioning.UserDataSecretRef, + case virtv2.ProvisioningTypeUserDataRef: + if opts.Provisioning.UserDataRef == nil { + return fmt.Errorf("nil user data ref: %s", opts.Provisioning.Type) + } + + switch opts.Provisioning.UserDataRef.Kind { + case virtv2.UserDataRefKindSecret: + vs.CloudInitNoCloud = &virtv1.CloudInitNoCloudSource{ + UserDataSecretRef: &corev1.LocalObjectReference{ + Name: opts.Provisioning.UserDataRef.Name, + }, + } + default: + return fmt.Errorf("unexpected user data ref kind: %s", opts.Provisioning.UserDataRef.Kind) } default: return fmt.Errorf("unexpected provisioning type %s. %w", opts.Provisioning.Type, common.ErrUnknownType) @@ -319,9 +341,9 @@ func (b *KVVM) SetProvisioning(p *virtv2.Provisioning) error { } switch p.Type { - case virtv2.ProvisioningTypeSysprepSecret: + case virtv2.ProvisioningTypeSysprepRef: return b.SetDisk(SysprepDiskName, SetDiskOptions{Provisioning: p, IsCdrom: true}) - case virtv2.ProvisioningTypeUserData, virtv2.ProvisioningTypeUserDataSecret: + case virtv2.ProvisioningTypeUserData, virtv2.ProvisioningTypeUserDataRef: return b.SetDisk(CloudInitDiskName, SetDiskOptions{Provisioning: p}) default: return fmt.Errorf("unexpected provisioning type %s. %w", p.Type, common.ErrUnknownType) diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go index 6bcc2fcb6..f4a6e4e78 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go @@ -15,9 +15,9 @@ import ( ) const ( - VMDDiskPrefix = "vmd-" - VMIDiskPrefix = "vmi-" - CVMIDiskPrefix = "cvmi-" + VMDDiskPrefix = "vd-" + VMIDiskPrefix = "vi-" + CVMIDiskPrefix = "cvi-" NetworkInterfaceName = "default" ) @@ -41,9 +41,9 @@ type HotPlugDeviceSettings struct { func ApplyVirtualMachineSpec( kvvm *KVVM, vm *virtv2.VirtualMachine, - vmdByName map[string]*virtv2.VirtualMachineDisk, - vmiByName map[string]*virtv2.VirtualMachineImage, - cvmiByName map[string]*virtv2.ClusterVirtualMachineImage, + vmdByName map[string]*virtv2.VirtualDisk, + vmiByName map[string]*virtv2.VirtualImage, + cvmiByName map[string]*virtv2.ClusterVirtualImage, dvcrSettings *dvcr.Settings, cpu virtv2.VirtualMachineCPUModelSpec, ipAddress string, @@ -91,20 +91,20 @@ func ApplyVirtualMachineSpec( } kvvm.ClearDisks() - for _, bd := range vm.Spec.BlockDevices { - switch bd.Type { + for _, bd := range vm.Spec.BlockDeviceRefs { + switch bd.Kind { case virtv2.ImageDevice: // Attach ephemeral disk for storage: Kubernetes. // Attach containerDisk for storage: ContainerRegistry (i.e. image from DVCR). - vmi := vmiByName[bd.VirtualMachineImage.Name] + vmi := vmiByName[bd.Name] - name := GenerateVMIDiskName(bd.VirtualMachineImage.Name) + name := GenerateVMIDiskName(bd.Name) switch vmi.Spec.Storage { case virtv2.StorageKubernetes: // Attach PVC as ephemeral volume: its data will be restored to initial state on VM restart. if err := kvvm.SetDisk(name, SetDiskOptions{ - PersistentVolumeClaim: util.GetPointer(vmi.Status.Target.PersistentVolumeClaimName), + PersistentVolumeClaim: util.GetPointer(vmi.Status.Target.PersistentVolumeClaim), IsEphemeral: true, Serial: name, }); err != nil { @@ -120,15 +120,15 @@ func ApplyVirtualMachineSpec( return err } default: - return fmt.Errorf("unexpected storage type %q for vmi %s. %w", vmi.Spec.Storage, vmi.Name, common.ErrUnknownType) + return fmt.Errorf("unexpected storage type %q for vi %s. %w", vmi.Spec.Storage, vmi.Name, common.ErrUnknownType) } case virtv2.ClusterImageDevice: - // ClusterVirtualMachineImage is attached as containerDisk. + // ClusterVirtualImage is attached as containerDisk. - cvmi := cvmiByName[bd.ClusterVirtualMachineImage.Name] + cvmi := cvmiByName[bd.Name] - name := GenerateCVMIDiskName(bd.ClusterVirtualMachineImage.Name) + name := GenerateCVMIDiskName(bd.Name) dvcrImage := dvcrSettings.RegistryImageForCVMI(cvmi.Name) if err := kvvm.SetDisk(name, SetDiskOptions{ ContainerDisk: util.GetPointer(dvcrImage), @@ -139,20 +139,20 @@ func ApplyVirtualMachineSpec( } case virtv2.DiskDevice: - // VirtualMachineDisk is attached as regular disk. + // VirtualDisk is attached as regular disk. - vmd := vmdByName[bd.VirtualMachineDisk.Name] + vmd := vmdByName[bd.Name] - name := GenerateVMDDiskName(bd.VirtualMachineDisk.Name) + name := GenerateVMDDiskName(bd.Name) if err := kvvm.SetDisk(name, SetDiskOptions{ - PersistentVolumeClaim: util.GetPointer(vmd.Status.Target.PersistentVolumeClaimName), + PersistentVolumeClaim: util.GetPointer(vmd.Status.Target.PersistentVolumeClaim), Serial: name, }); err != nil { return err } default: - return fmt.Errorf("unknown block device type %q. %w", bd.Type, common.ErrUnknownType) + return fmt.Errorf("unknown block device kind %q. %w", bd.Kind, common.ErrUnknownType) } } diff --git a/images/virtualization-artifact/pkg/controller/vm_annotations.go b/images/virtualization-artifact/pkg/controller/vm_annotations.go deleted file mode 100644 index b0b429f89..000000000 --- a/images/virtualization-artifact/pkg/controller/vm_annotations.go +++ /dev/null @@ -1 +0,0 @@ -package controller diff --git a/images/virtualization-artifact/pkg/controller/vm_reconciler.go b/images/virtualization-artifact/pkg/controller/vm_reconciler.go index 5fdddf519..692e69014 100644 --- a/images/virtualization-artifact/pkg/controller/vm_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/vm_reconciler.go @@ -77,6 +77,32 @@ func (r *VMReconciler) SetupController(_ context.Context, mgr manager.Manager, c return fmt.Errorf("error setting watch on VirtualMachine: %w", err) } + // Subscribe on Kubevirt VirtualMachineInstances to update our VM status. + if err := ctr.Watch( + source.Kind(mgr.GetCache(), &virtv1.VirtualMachineInstance{}), + handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, vmi client.Object) []reconcile.Request { + return []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Name: vmi.GetName(), + Namespace: vmi.GetNamespace(), + }, + }, + } + }), + predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { return true }, + DeleteFunc: func(e event.DeleteEvent) bool { return true }, + UpdateFunc: func(e event.UpdateEvent) bool { + oldVM := e.ObjectOld.(*virtv1.VirtualMachineInstance) + newVM := e.ObjectNew.(*virtv1.VirtualMachineInstance) + return oldVM.Status.Phase != newVM.Status.Phase + }, + }, + ); err != nil { + return fmt.Errorf("error setting watch on VirtualMachine: %w", err) + } + // Watch for Pods created on behalf of VMs. Handle only changes in status.phase. // Pod tracking is required to detect when Pod becomes Completed after guest initiated reset or shutdown. if err := ctr.Watch( @@ -270,7 +296,7 @@ func (r *VMReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, stat return nil } - state.VM.Changed().Status.IPAddressClaim = state.IPAddressClaim.Name + state.VM.Changed().Status.VirtualMachineIPAddressClaim = state.IPAddressClaim.Name state.VM.Changed().Status.IPAddress = state.IPAddressClaim.Spec.Address if !state.BlockDevicesReady() { @@ -296,7 +322,7 @@ func (r *VMReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, stat // TODO We need to rerun this block because KVVMI status fields may be updated with a delay. state.VM.Changed().Status.Phase = virtv2.MachineRunning state.VM.Changed().Status.GuestOSInfo = state.KVVMI.Status.GuestOSInfo - state.VM.Changed().Status.NodeName = state.KVVMI.Status.NodeName + state.VM.Changed().Status.Node = state.KVVMI.Status.NodeName for _, iface := range state.KVVMI.Status.Interfaces { if iface.Name == kvbuilder.NetworkInterfaceName { hasClaimedIP := false @@ -312,11 +338,11 @@ func (r *VMReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, stat break } } - for _, bd := range state.VM.Current().Spec.BlockDevices { - if state.FindAttachedBlockDevice(bd) == nil { - if abd := state.CreateAttachedBlockDevice(bd); abd != nil { - state.VM.Changed().Status.BlockDevicesAttached = append( - state.VM.Changed().Status.BlockDevicesAttached, + for _, ref := range state.VM.Current().Spec.BlockDeviceRefs { + if state.FindAttachedBlockDevice(ref) == nil { + if abd := state.CreateAttachedBlockDevice(ref); abd != nil { + state.VM.Changed().Status.BlockDeviceRefs = append( + state.VM.Changed().Status.BlockDeviceRefs, *abd, ) } @@ -360,9 +386,9 @@ func (r *VMReconciler) ensureIPAddressClaim(ctx context.Context, state *VMReconc // 2. Claim not found: create if possible or wait for the claim. if state.IPAddressClaim == nil { - if state.VM.Current().Spec.VirtualMachineIPAddressClaimName != "" { - opts.Log.Info(fmt.Sprintf("The requested ip address claim (%s) for the virtual machine not found: waiting for the Claim", state.VM.Current().Spec.VirtualMachineIPAddressClaimName)) - state.SetStatusMessage(fmt.Sprintf("The requested ip address claim (%s) for the virtual machine not found: waiting for the Claim", state.VM.Current().Spec.VirtualMachineIPAddressClaimName)) + if state.VM.Current().Spec.VirtualMachineIPAddressClaim != "" { + opts.Log.Info(fmt.Sprintf("The requested ip address claim (%s) for the virtual machine not found: waiting for the Claim", state.VM.Current().Spec.VirtualMachineIPAddressClaim)) + state.SetStatusMessage(fmt.Sprintf("The requested ip address claim (%s) for the virtual machine not found: waiting for the Claim", state.VM.Current().Spec.VirtualMachineIPAddressClaim)) state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) return false, nil @@ -378,7 +404,7 @@ func (r *VMReconciler) ensureIPAddressClaim(ctx context.Context, state *VMReconc // 3. Check if possible to bind virtual machine with the found claim. err := r.ipam.CheckClaimAvailableForBinding(state.VM.Name().Name, state.IPAddressClaim) if err != nil { - opts.Log.Info("Claim is not available to be bound", "err", err, "claimName", state.VM.Current().Spec.VirtualMachineIPAddressClaimName) + opts.Log.Info("Claim is not available to be bound", "err", err, "claimName", state.VM.Current().Spec.VirtualMachineIPAddressClaim) state.SetStatusMessage(err.Error()) opts.Recorder.Event(state.VM.Current(), corev1.EventTypeWarning, virtv2.ReasonClaimNotAvailable, err.Error()) @@ -386,7 +412,7 @@ func (r *VMReconciler) ensureIPAddressClaim(ctx context.Context, state *VMReconc } // 4. Claim exists and available for binding with virtual machine: waiting for the claim. - opts.Log.Info("Waiting for the Claim to be bound to VM", "claimName", state.VM.Current().Spec.VirtualMachineIPAddressClaimName) + opts.Log.Info("Waiting for the Claim to be bound to VM", "claimName", state.VM.Current().Spec.VirtualMachineIPAddressClaim) state.SetStatusMessage("Claim not bound: waiting for the Claim") state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) @@ -432,17 +458,16 @@ func (r *VMReconciler) checkBlockDevicesSanity(state *VMReconcilerState) string disks := make([]string, 0) hotplugged := make(map[string]struct{}) - for _, bda := range state.VM.Current().Status.BlockDevicesAttached { - if bda.Hotpluggable && bda.VirtualMachineDisk != nil { - hotplugged[bda.VirtualMachineDisk.Name] = struct{}{} + for _, bda := range state.VM.Current().Status.BlockDeviceRefs { + if bda.Hotpluggable { + hotplugged[bda.Name] = struct{}{} } } - for _, bd := range state.VM.Current().Spec.BlockDevices { - disk := bd.VirtualMachineDisk - if disk != nil { - if _, ok := hotplugged[disk.Name]; ok { - disks = append(disks, disk.Name) + for _, bd := range state.VM.Current().Spec.BlockDeviceRefs { + if bd.Kind == virtv2.DiskDevice { + if _, ok := hotplugged[bd.Name]; ok { + disks = append(disks, bd.Name) } } } @@ -451,7 +476,7 @@ func (r *VMReconciler) checkBlockDevicesSanity(state *VMReconcilerState) string return "" } - return fmt.Sprintf("spec.blockDevices contain hotplugged disks: %s. Unplug or remove them from spec to continue.", strings.Join(disks, ", ")) + return fmt.Sprintf("spec.blockDeviceRefs contain hotplugged disks: %s. Unplug or remove them from spec to continue.", strings.Join(disks, ", ")) } func (r *VMReconciler) makeKVVMFromVMSpec(state *VMReconcilerState) (*virtv1.VirtualMachine, error) { @@ -490,7 +515,7 @@ func (r *VMReconciler) makeKVVMFromVMSpec(state *VMReconcilerState) (*virtv1.Vir func (r *VMReconciler) createKVVM(ctx context.Context, state *VMReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { kvvm, err := r.makeKVVMFromVMSpec(state) if err != nil { - return fmt.Errorf("prepare to create KubeVirt VM '%s': %w", kvvm.GetName(), err) + return fmt.Errorf("prepare to create KubeVirt VM '%s': %w", state.VM.Name().Name, err) } if err := opts.Client.Create(ctx, kvvm); err != nil { diff --git a/images/virtualization-artifact/pkg/controller/vm_reconciler_state.go b/images/virtualization-artifact/pkg/controller/vm_reconciler_state.go index 3925c6417..e00827272 100644 --- a/images/virtualization-artifact/pkg/controller/vm_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/vm_reconciler_state.go @@ -25,7 +25,6 @@ import ( "github.com/deckhouse/virtualization-controller/pkg/controller/powerstate" "github.com/deckhouse/virtualization-controller/pkg/controller/vmchange" "github.com/deckhouse/virtualization-controller/pkg/sdk/framework/helper" - "github.com/deckhouse/virtualization-controller/pkg/util" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" ) @@ -36,9 +35,9 @@ type VMReconcilerState struct { KVVMI *virtv1.VirtualMachineInstance KVPods *corev1.PodList VMPod *corev1.Pod - VMDByName map[string]*virtv2.VirtualMachineDisk - VMIByName map[string]*virtv2.VirtualMachineImage - CVMIByName map[string]*virtv2.ClusterVirtualMachineImage + VMDByName map[string]*virtv2.VirtualDisk + VMIByName map[string]*virtv2.VirtualImage + CVMIByName map[string]*virtv2.ClusterVirtualImage IPAddressClaim *virtv2.VirtualMachineIPAddressClaim CPUModel *virtv2.VirtualMachineCPUModel @@ -92,7 +91,7 @@ func (state *VMReconcilerState) Reload(ctx context.Context, req reconcile.Reques return nil } - claimName := state.VM.Current().Spec.VirtualMachineIPAddressClaimName + claimName := state.VM.Current().Spec.VirtualMachineIPAddressClaim if claimName == "" { claimName = state.VM.Name().Name } @@ -103,7 +102,7 @@ func (state *VMReconcilerState) Reload(ctx context.Context, req reconcile.Reques return fmt.Errorf("unable to get Claim %s: %w", claimKey, err) } - vmcpuKey := types.NamespacedName{Name: state.VM.Current().Spec.CPU.ModelName} + vmcpuKey := types.NamespacedName{Name: state.VM.Current().Spec.CPU.VirtualMachineCPUModel} state.CPUModel, err = helper.FetchObject(ctx, vmcpuKey, state.Client, &virtv2.VirtualMachineCPUModel{}) if err != nil { return fmt.Errorf("unable to get cpu model %s: %w", claimKey, err) @@ -147,61 +146,61 @@ func (state *VMReconcilerState) Reload(ctx context.Context, req reconcile.Reques // Get shutdown reason if VM is completed. state.VMPodCompleted, state.VMShutdownReason = powerstate.ShutdownReason(state.KVVMI, state.KVPods) - var vmdByName map[string]*virtv2.VirtualMachineDisk - var vmiByName map[string]*virtv2.VirtualMachineImage - var cvmiByName map[string]*virtv2.ClusterVirtualMachineImage + var vmdByName map[string]*virtv2.VirtualDisk + var vmiByName map[string]*virtv2.VirtualImage + var cvmiByName map[string]*virtv2.ClusterVirtualImage - for _, bd := range state.VM.Current().Spec.BlockDevices { - switch bd.Type { + for _, bd := range state.VM.Current().Spec.BlockDeviceRefs { + switch bd.Kind { case virtv2.ImageDevice: vmi, err := helper.FetchObject(ctx, types.NamespacedName{ - Name: bd.VirtualMachineImage.Name, + Name: bd.Name, Namespace: state.VM.Name().Namespace, - }, state.Client, &virtv2.VirtualMachineImage{}) + }, state.Client, &virtv2.VirtualImage{}) if err != nil { - return fmt.Errorf("unable to get VMI %q: %w", bd.VirtualMachineImage.Name, err) + return fmt.Errorf("unable to get VI %q: %w", bd.Name, err) } if vmi == nil { continue } if vmiByName == nil { - vmiByName = make(map[string]*virtv2.VirtualMachineImage) + vmiByName = make(map[string]*virtv2.VirtualImage) } - vmiByName[bd.VirtualMachineImage.Name] = vmi + vmiByName[bd.Name] = vmi case virtv2.ClusterImageDevice: cvmi, err := helper.FetchObject(ctx, types.NamespacedName{ - Name: bd.ClusterVirtualMachineImage.Name, - }, state.Client, &virtv2.ClusterVirtualMachineImage{}) + Name: bd.Name, + }, state.Client, &virtv2.ClusterVirtualImage{}) if err != nil { - return fmt.Errorf("unable to get CVMI %q: %w", bd.ClusterVirtualMachineImage.Name, err) + return fmt.Errorf("unable to get CVI %q: %w", bd.Name, err) } if cvmi == nil { continue } if cvmiByName == nil { - cvmiByName = make(map[string]*virtv2.ClusterVirtualMachineImage) + cvmiByName = make(map[string]*virtv2.ClusterVirtualImage) } - cvmiByName[bd.ClusterVirtualMachineImage.Name] = cvmi + cvmiByName[bd.Name] = cvmi case virtv2.DiskDevice: vmd, err := helper.FetchObject(ctx, types.NamespacedName{ - Name: bd.VirtualMachineDisk.Name, + Name: bd.Name, Namespace: state.VM.Name().Namespace, - }, state.Client, &virtv2.VirtualMachineDisk{}) + }, state.Client, &virtv2.VirtualDisk{}) if err != nil { - return fmt.Errorf("unable to get VMD %q: %w", bd.VirtualMachineDisk.Name, err) + return fmt.Errorf("unable to get virtual disk %q: %w", bd.Name, err) } if vmd == nil { continue } if vmdByName == nil { - vmdByName = make(map[string]*virtv2.VirtualMachineDisk) + vmdByName = make(map[string]*virtv2.VirtualDisk) } - vmdByName[bd.VirtualMachineDisk.Name] = vmd + vmdByName[bd.Name] = vmd default: - return fmt.Errorf("unexpected block device type %q. %w", bd.Type, common.ErrUnknownType) + return fmt.Errorf("unexpected block device kind %q. %w", bd.Kind, common.ErrUnknownType) } } @@ -242,80 +241,71 @@ func (state *VMReconcilerState) ResetChangesInfo() { state.StatusMessage = "" } -func (state *VMReconcilerState) FindAttachedBlockDevice(spec virtv2.BlockDeviceSpec) *virtv2.BlockDeviceStatus { - for i := range state.VM.Current().Status.BlockDevicesAttached { - bda := &state.VM.Current().Status.BlockDevicesAttached[i] - switch spec.Type { - case virtv2.DiskDevice: - if bda.Type == spec.Type && bda.VirtualMachineDisk.Name == spec.VirtualMachineDisk.Name { - return bda - } - - case virtv2.ImageDevice: - if bda.Type == spec.Type && bda.VirtualMachineImage.Name == spec.VirtualMachineImage.Name { - return bda - } - - case virtv2.ClusterImageDevice: - if bda.Type == spec.Type && bda.ClusterVirtualMachineImage.Name == spec.ClusterVirtualMachineImage.Name { - return bda - } +func (state *VMReconcilerState) FindAttachedBlockDevice(spec virtv2.BlockDeviceSpecRef) *virtv2.BlockDeviceStatusRef { + for i := range state.VM.Current().Status.BlockDeviceRefs { + bda := &state.VM.Current().Status.BlockDeviceRefs[i] + if bda.Kind == spec.Kind && bda.Name == spec.Name { + return bda } } + return nil } -func (state *VMReconcilerState) CreateAttachedBlockDevice(spec virtv2.BlockDeviceSpec) *virtv2.BlockDeviceStatus { - switch spec.Type { +func (state *VMReconcilerState) CreateAttachedBlockDevice(spec virtv2.BlockDeviceSpecRef) *virtv2.BlockDeviceStatusRef { + switch spec.Kind { case virtv2.ImageDevice: - vs := state.FindVolumeStatus(kvbuilder.GenerateVMIDiskName(spec.VirtualMachineImage.Name)) + vs := state.FindVolumeStatus(kvbuilder.GenerateVMIDiskName(spec.Name)) if vs == nil { return nil } - vmi, hasVMI := state.VMIByName[spec.VirtualMachineImage.Name] + vmi, hasVMI := state.VMIByName[spec.Name] if !hasVMI { return nil } - return &virtv2.BlockDeviceStatus{ - Type: virtv2.ImageDevice, - VirtualMachineImage: util.CopyByPointer(spec.VirtualMachineImage), - Target: vs.Target, - Size: vmi.Status.Capacity, + + return &virtv2.BlockDeviceStatusRef{ + Kind: virtv2.ImageDevice, + Name: spec.Name, + Target: vs.Target, + Size: vmi.Status.Capacity, } case virtv2.DiskDevice: - vs := state.FindVolumeStatus(kvbuilder.GenerateVMDDiskName(spec.VirtualMachineDisk.Name)) + vs := state.FindVolumeStatus(kvbuilder.GenerateVMDDiskName(spec.Name)) if vs == nil { return nil } - vmd, hasVmd := state.VMDByName[spec.VirtualMachineDisk.Name] + vmd, hasVmd := state.VMDByName[spec.Name] if !hasVmd { return nil } - return &virtv2.BlockDeviceStatus{ - Type: virtv2.DiskDevice, - VirtualMachineDisk: util.CopyByPointer(spec.VirtualMachineDisk), - Target: vs.Target, - Size: vmd.Status.Capacity, + + return &virtv2.BlockDeviceStatusRef{ + Kind: virtv2.DiskDevice, + Name: spec.Name, + Target: vs.Target, + Size: vmd.Status.Capacity, } case virtv2.ClusterImageDevice: - vs := state.FindVolumeStatus(kvbuilder.GenerateCVMIDiskName(spec.ClusterVirtualMachineImage.Name)) + vs := state.FindVolumeStatus(kvbuilder.GenerateCVMIDiskName(spec.Name)) if vs == nil { return nil } - cvmi, hasCvmi := state.CVMIByName[spec.ClusterVirtualMachineImage.Name] + cvmi, hasCvmi := state.CVMIByName[spec.Name] if !hasCvmi { return nil } - return &virtv2.BlockDeviceStatus{ - Type: virtv2.ClusterImageDevice, - ClusterVirtualMachineImage: util.CopyByPointer(spec.ClusterVirtualMachineImage), - Target: vs.Target, - Size: cvmi.Status.Size.Unpacked, + + return &virtv2.BlockDeviceStatusRef{ + Kind: virtv2.ClusterImageDevice, + Name: spec.Name, + Target: vs.Target, + Size: cvmi.Status.Size.Unpacked, } } return nil @@ -333,34 +323,34 @@ func (state *VMReconcilerState) FindVolumeStatus(volumeName string) *virtv1.Volu // SetFinalizersOnBlockDevices sets protection finalizers on CVMI and VMD attached to the VM. func (state *VMReconcilerState) SetFinalizersOnBlockDevices(ctx context.Context) error { - for _, bd := range state.VM.Current().Spec.BlockDevices { - switch bd.Type { + for _, bd := range state.VM.Current().Spec.BlockDeviceRefs { + switch bd.Kind { case virtv2.ImageDevice: - if vmi, hasKey := state.VMIByName[bd.VirtualMachineImage.Name]; hasKey { + if vmi, hasKey := state.VMIByName[bd.Name]; hasKey { if controllerutil.AddFinalizer(vmi, virtv2.FinalizerVMIProtection) { if err := state.Client.Update(ctx, vmi); err != nil { - return fmt.Errorf("error setting finalizer on a VMI %q: %w", vmi.Name, err) + return fmt.Errorf("error setting finalizer on a VI %q: %w", vmi.Name, err) } } } case virtv2.ClusterImageDevice: - if cvmi, hasKey := state.CVMIByName[bd.ClusterVirtualMachineImage.Name]; hasKey { + if cvmi, hasKey := state.CVMIByName[bd.Name]; hasKey { if controllerutil.AddFinalizer(cvmi, virtv2.FinalizerCVMIProtection) { if err := state.Client.Update(ctx, cvmi); err != nil { - return fmt.Errorf("error setting finalizer on a CVMI %q: %w", cvmi.Name, err) + return fmt.Errorf("error setting finalizer on a CVI %q: %w", cvmi.Name, err) } } } case virtv2.DiskDevice: - if vmd, hasKey := state.VMDByName[bd.VirtualMachineDisk.Name]; hasKey { + if vmd, hasKey := state.VMDByName[bd.Name]; hasKey { if controllerutil.AddFinalizer(vmd, virtv2.FinalizerVMDProtection) { if err := state.Client.Update(ctx, vmd); err != nil { - return fmt.Errorf("error setting finalizer on a VMD %q: %w", vmd.Name, err) + return fmt.Errorf("error setting finalizer on a virtual disk %q: %w", vmd.Name, err) } } } default: - return fmt.Errorf("unexpected block device type %q. %w", bd.Type, common.ErrUnknownType) + return fmt.Errorf("unexpected block device kind %q. %w", bd.Kind, common.ErrUnknownType) } } @@ -369,10 +359,10 @@ func (state *VMReconcilerState) SetFinalizersOnBlockDevices(ctx context.Context) // BlockDevicesReady check if all attached images and disks are ready to use by the VM. func (state *VMReconcilerState) BlockDevicesReady() bool { - for _, bd := range state.VM.Current().Spec.BlockDevices { - switch bd.Type { + for _, bd := range state.VM.Current().Spec.BlockDeviceRefs { + switch bd.Kind { case virtv2.ImageDevice: - if vmi, hasKey := state.VMIByName[bd.VirtualMachineImage.Name]; hasKey { + if vmi, hasKey := state.VMIByName[bd.Name]; hasKey { if vmi.Status.Phase != virtv2.ImageReady { return false } @@ -381,7 +371,7 @@ func (state *VMReconcilerState) BlockDevicesReady() bool { } case virtv2.ClusterImageDevice: - if cvmi, hasKey := state.CVMIByName[bd.ClusterVirtualMachineImage.Name]; hasKey { + if cvmi, hasKey := state.CVMIByName[bd.Name]; hasKey { if cvmi.Status.Phase != virtv2.ImageReady { return false } @@ -390,7 +380,7 @@ func (state *VMReconcilerState) BlockDevicesReady() bool { } case virtv2.DiskDevice: - if vmd, hasKey := state.VMDByName[bd.VirtualMachineDisk.Name]; hasKey { + if vmd, hasKey := state.VMDByName[bd.Name]; hasKey { if vmd.Status.Phase != virtv2.DiskReady { return false } diff --git a/images/virtualization-artifact/pkg/controller/vm_reconciler_state_test.go b/images/virtualization-artifact/pkg/controller/vm_reconciler_state_test.go index a2b17a8f2..6e6086d1b 100644 --- a/images/virtualization-artifact/pkg/controller/vm_reconciler_state_test.go +++ b/images/virtualization-artifact/pkg/controller/vm_reconciler_state_test.go @@ -35,10 +35,10 @@ func TestUnmarshalVMStatus(t *testing.T) { Memory: v1alpha2.MemorySpec{ Size: "2Gi", }, - BlockDevices: []v1alpha2.BlockDeviceSpec{ + BlockDeviceRefs: []v1alpha2.BlockDeviceSpecRef{ { - Type: v1alpha2.DiskDevice, - VirtualMachineDisk: &v1alpha2.DiskDeviceSpec{Name: "test-vmd"}, + Kind: v1alpha2.DiskDevice, + Name: "test-vmd", }, }, Disruptions: &v1alpha2.Disruptions{RestartApprovalMode: v1alpha2.Automatic}, diff --git a/images/virtualization-artifact/pkg/controller/vm_reconciler_test.go b/images/virtualization-artifact/pkg/controller/vm_reconciler_test.go index 3b6f29d2f..b15e7a7d0 100644 --- a/images/virtualization-artifact/pkg/controller/vm_reconciler_test.go +++ b/images/virtualization-artifact/pkg/controller/vm_reconciler_test.go @@ -63,21 +63,21 @@ var _ = Describe("VM", func() { Annotations: testVMAnno, }, Spec: virtv2.VirtualMachineSpec{ - VirtualMachineIPAddressClaimName: "test-vmip", - RunPolicy: virtv2.AlwaysOnPolicy, - EnableParavirtualization: true, - OsType: virtv2.GenericOs, + VirtualMachineIPAddressClaim: "test-vmip", + RunPolicy: virtv2.AlwaysOnPolicy, + EnableParavirtualization: true, + OsType: virtv2.GenericOs, CPU: virtv2.CPUSpec{ - ModelName: "test-vmcpu", - Cores: 2, + VirtualMachineCPUModel: "test-vmcpu", + Cores: 2, }, Memory: virtv2.MemorySpec{ Size: "2Gi", }, - BlockDevices: []virtv2.BlockDeviceSpec{ + BlockDeviceRefs: []virtv2.BlockDeviceSpecRef{ { - Type: virtv2.DiskDevice, - VirtualMachineDisk: &virtv2.DiskDeviceSpec{Name: "test-vmd"}, + Kind: virtv2.DiskDevice, + Name: "test-vmd", }, }, Disruptions: &virtv2.Disruptions{RestartApprovalMode: virtv2.Automatic}, @@ -88,8 +88,8 @@ var _ = Describe("VM", func() { reconciler = controller.NewTestVMReconciler(controller.TestReconcilerOptions{ KnownObjects: []client.Object{ &virtv2.VirtualMachine{}, - &virtv2.VirtualMachineDisk{}, - &virtv2.ClusterVirtualMachineImage{}, + &virtv2.VirtualDisk{}, + &virtv2.ClusterVirtualImage{}, &virtv2.VirtualMachineIPAddressClaim{}, &virtv1.VirtualMachine{}, &virtv1.VirtualMachineInstance{}, @@ -146,30 +146,30 @@ var _ = Describe("VM", func() { kvvm, err := helper.FetchObject(ctx, types.NamespacedName{Name: vm.Name, Namespace: "test-ns"}, reconciler.Client, &virtv1.VirtualMachine{}) Expect(err).NotTo(HaveOccurred()) - Expect(kvvm).To(BeNil(), fmt.Sprintf("Unexpected KubeVirt VM %q to be existing when no VMD exists in the system", vm.Name)) + Expect(kvvm).To(BeNil(), fmt.Sprintf("Unexpected KubeVirt VM %q to be existing when no VD exists in the system", vm.Name)) } { storageClassName := "local-path" - vmd := &virtv2.VirtualMachineDisk{ + vmd := &virtv2.VirtualDisk{ ObjectMeta: metav1.ObjectMeta{ Namespace: "test-ns", Name: "test-vmd", Labels: nil, Annotations: nil, }, - Spec: virtv2.VirtualMachineDiskSpec{ - DataSource: &virtv2.VMDDataSource{ + Spec: virtv2.VirtualDiskSpec{ + DataSource: &virtv2.VirtualDiskDataSource{ HTTP: &virtv2.DataSourceHTTP{ URL: "http://mydomain.org/image.img", }, }, - PersistentVolumeClaim: virtv2.VMDPersistentVolumeClaim{ - Size: resource.NewQuantity(10*1024*1024*1024, resource.BinarySI), - StorageClassName: &storageClassName, + PersistentVolumeClaim: virtv2.VirtualDiskPersistentVolumeClaim{ + Size: resource.NewQuantity(10*1024*1024*1024, resource.BinarySI), + StorageClass: &storageClassName, }, }, - Status: virtv2.VirtualMachineDiskStatus{ + Status: virtv2.VirtualDiskStatus{ Phase: virtv2.DiskPending, Capacity: "10Gi", }, @@ -187,11 +187,11 @@ var _ = Describe("VM", func() { kvvm, err := helper.FetchObject(ctx, types.NamespacedName{Name: vm.Name, Namespace: "test-ns"}, reconciler.Client, &virtv1.VirtualMachine{}) Expect(err).NotTo(HaveOccurred()) - Expect(kvvm).To(BeNil(), fmt.Sprintf("Unexpected KubeVirt VM %q to be existing when VMD not ready yet", vm.Name)) + Expect(kvvm).To(BeNil(), fmt.Sprintf("Unexpected KubeVirt VM %q to be existing when VD not ready yet", vm.Name)) } { - vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualMachineDisk{}) + vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualDisk{}) Expect(err).NotTo(HaveOccurred()) Expect(vmd).NotTo(BeNil()) vmd.Status.Phase = virtv2.DiskReady @@ -329,16 +329,12 @@ var _ = Describe("VM", func() { Expect(vm).NotTo(BeNil()) Expect(vm.Status.Phase).To(Equal(virtv2.MachineRunning)) Expect(reflect.DeepEqual(vm.Status.GuestOSInfo, kvvmi.Status.GuestOSInfo)).To(BeTrue(), fmt.Sprintf("unequal GuestOSInfo %#v != %#v", vm.Status.GuestOSInfo, kvvmi.Status.GuestOSInfo)) - Expect(vm.Status.NodeName).To(Equal(kvvmi.Status.NodeName)) + Expect(vm.Status.Node).To(Equal(kvvmi.Status.NodeName)) Expect(vm.Status.IPAddress).To(Equal(kvvmi.Status.Interfaces[0].IP)) - Expect(vm.Status.BlockDevicesAttached[0].Type).To(Equal(virtv2.DiskDevice)) - Expect(vm.Status.BlockDevicesAttached[0].VirtualMachineImage).To(BeNil()) - Expect(reflect.DeepEqual( - *vm.Status.BlockDevicesAttached[0].VirtualMachineDisk, - virtv2.DiskDeviceSpec{Name: "test-vmd"}, - )).To(BeTrue()) - Expect(vm.Status.BlockDevicesAttached[0].Target).To(Equal(kvvmi.Status.VolumeStatus[0].Target)) - Expect(vm.Status.BlockDevicesAttached[0].Size).To(Equal("10Gi")) + Expect(vm.Status.BlockDeviceRefs[0].Kind).To(Equal(virtv2.DiskDevice)) + Expect(vm.Status.BlockDeviceRefs[0].Name).To(Equal("test-vmd")) + Expect(vm.Status.BlockDeviceRefs[0].Target).To(Equal(kvvmi.Status.VolumeStatus[0].Target)) + Expect(vm.Status.BlockDeviceRefs[0].Size).To(Equal("10Gi")) } { @@ -403,21 +399,21 @@ var _ = Describe("Apply VM changes", func() { Name: vmName, }, Spec: virtv2.VirtualMachineSpec{ - VirtualMachineIPAddressClaimName: vmipName, - RunPolicy: virtv2.AlwaysOnPolicy, - EnableParavirtualization: true, - OsType: virtv2.GenericOs, + VirtualMachineIPAddressClaim: vmipName, + RunPolicy: virtv2.AlwaysOnPolicy, + EnableParavirtualization: true, + OsType: virtv2.GenericOs, CPU: virtv2.CPUSpec{ - ModelName: vmcpuName, - Cores: 2, + VirtualMachineCPUModel: vmcpuName, + Cores: 2, }, Memory: virtv2.MemorySpec{ Size: "2Gi", }, - BlockDevices: []virtv2.BlockDeviceSpec{ + BlockDeviceRefs: []virtv2.BlockDeviceSpecRef{ { - Type: virtv2.DiskDevice, - VirtualMachineDisk: &virtv2.DiskDeviceSpec{Name: vmdName}, + Kind: virtv2.DiskDevice, + Name: vmdName, }, }, Disruptions: &virtv2.Disruptions{RestartApprovalMode: virtv2.Automatic}, @@ -425,23 +421,23 @@ var _ = Describe("Apply VM changes", func() { Status: virtv2.VirtualMachineStatus{}, } - vmd := &virtv2.VirtualMachineDisk{ + vmd := &virtv2.VirtualDisk{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName, Name: vmdName, }, - Spec: virtv2.VirtualMachineDiskSpec{ - DataSource: &virtv2.VMDDataSource{ + Spec: virtv2.VirtualDiskSpec{ + DataSource: &virtv2.VirtualDiskDataSource{ HTTP: &virtv2.DataSourceHTTP{ URL: "http://mydomain.org/image.img", }, }, - PersistentVolumeClaim: virtv2.VMDPersistentVolumeClaim{ - Size: resource.NewQuantity(10*1024*1024*1024, resource.BinarySI), - StorageClassName: &storageClassName, + PersistentVolumeClaim: virtv2.VirtualDiskPersistentVolumeClaim{ + Size: resource.NewQuantity(10*1024*1024*1024, resource.BinarySI), + StorageClass: &storageClassName, }, }, - Status: virtv2.VirtualMachineDiskStatus{ + Status: virtv2.VirtualDiskStatus{ Phase: virtv2.DiskReady, Capacity: "10Gi", }, @@ -450,8 +446,8 @@ var _ = Describe("Apply VM changes", func() { reconciler = controller.NewTestVMReconciler(controller.TestReconcilerOptions{ KnownObjects: []client.Object{ &virtv2.VirtualMachine{}, - &virtv2.VirtualMachineDisk{}, - &virtv2.ClusterVirtualMachineImage{}, + &virtv2.VirtualDisk{}, + &virtv2.ClusterVirtualImage{}, &virtv1.VirtualMachine{}, &virtv1.VirtualMachineInstance{}, }, @@ -558,22 +554,22 @@ var _ = Describe("Apply VM changes with manual approval", func() { Name: vmName, }, Spec: virtv2.VirtualMachineSpec{ - VirtualMachineIPAddressClaimName: vmipName, - RunPolicy: virtv2.AlwaysOnPolicy, - EnableParavirtualization: true, - OsType: virtv2.GenericOs, + VirtualMachineIPAddressClaim: vmipName, + RunPolicy: virtv2.AlwaysOnPolicy, + EnableParavirtualization: true, + OsType: virtv2.GenericOs, CPU: virtv2.CPUSpec{ - ModelName: vmcpuName, - Cores: cpuStartingCores, - CoreFraction: cpuStartingCoreFraction, + VirtualMachineCPUModel: vmcpuName, + Cores: cpuStartingCores, + CoreFraction: cpuStartingCoreFraction, }, Memory: virtv2.MemorySpec{ Size: memoryStartingSize, }, - BlockDevices: []virtv2.BlockDeviceSpec{ + BlockDeviceRefs: []virtv2.BlockDeviceSpecRef{ { - Type: virtv2.DiskDevice, - VirtualMachineDisk: &virtv2.DiskDeviceSpec{Name: vmdName}, + Kind: virtv2.DiskDevice, + Name: vmdName, }, }, Disruptions: &virtv2.Disruptions{RestartApprovalMode: virtv2.Manual}, @@ -581,23 +577,23 @@ var _ = Describe("Apply VM changes with manual approval", func() { Status: virtv2.VirtualMachineStatus{}, } - vmd := &virtv2.VirtualMachineDisk{ + vmd := &virtv2.VirtualDisk{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName, Name: vmdName, }, - Spec: virtv2.VirtualMachineDiskSpec{ - DataSource: &virtv2.VMDDataSource{ + Spec: virtv2.VirtualDiskSpec{ + DataSource: &virtv2.VirtualDiskDataSource{ HTTP: &virtv2.DataSourceHTTP{ URL: "http://mydomain.org/image.img", }, }, - PersistentVolumeClaim: virtv2.VMDPersistentVolumeClaim{ - Size: resource.NewQuantity(10*1024*1024*1024, resource.BinarySI), - StorageClassName: &storageClassName, + PersistentVolumeClaim: virtv2.VirtualDiskPersistentVolumeClaim{ + Size: resource.NewQuantity(10*1024*1024*1024, resource.BinarySI), + StorageClass: &storageClassName, }, }, - Status: virtv2.VirtualMachineDiskStatus{ + Status: virtv2.VirtualDiskStatus{ Phase: virtv2.DiskReady, Capacity: "10Gi", }, @@ -606,8 +602,8 @@ var _ = Describe("Apply VM changes with manual approval", func() { reconciler = controller.NewTestVMReconciler(controller.TestReconcilerOptions{ KnownObjects: []client.Object{ &virtv2.VirtualMachine{}, - &virtv2.VirtualMachineDisk{}, - &virtv2.ClusterVirtualMachineImage{}, + &virtv2.VirtualDisk{}, + &virtv2.ClusterVirtualImage{}, &virtv1.VirtualMachine{}, &virtv1.VirtualMachineInstance{}, }, @@ -641,7 +637,7 @@ var _ = Describe("Apply VM changes with manual approval", func() { CreateReadyVM(ctx, reconciler, reconcileExecutor, vm, vmd) - By("Emulating kubevirt: create kubevirt VMI in Ready status") + By("Emulating kubevirt: create kubevirt VI in Ready status") // Ensure kubevirt VMI is present. kvvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmName, Namespace: nsName}, reconciler.Client, &virtv1.VirtualMachineInstance{}) @@ -669,7 +665,7 @@ var _ = Describe("Apply VM changes with manual approval", func() { } { - By("Checking kubevirt VMI was not deleted") + By("Checking kubevirt VI was not deleted") // Check that kubevirt VMI was not deleted. kvvmi, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmName, Namespace: nsName}, reconciler.Client, &virtv1.VirtualMachineInstance{}) Expect(err).ShouldNot(HaveOccurred()) @@ -698,14 +694,14 @@ var _ = Describe("Apply VM changes with manual approval", func() { "path": Equal("cpu"), "operation": Equal(string(vmchange.ChangeReplace)), "currentValue": MatchAllKeys(Keys{ - "modelName": BeEquivalentTo(vmcpuName), - "cores": BeEquivalentTo(cpuStartingCores), - "coreFraction": Equal(cpuStartingCoreFraction), + "virtualMachineCPUModel": BeEquivalentTo(vmcpuName), + "cores": BeEquivalentTo(cpuStartingCores), + "coreFraction": Equal(cpuStartingCoreFraction), }), "desiredValue": MatchAllKeys(Keys{ - "modelName": BeEquivalentTo(vmcpuName), - "cores": BeEquivalentTo(cpuNewCores), - "coreFraction": Equal(cpuNewCoreFraction), + "virtualMachineCPUModel": BeEquivalentTo(vmcpuName), + "cores": BeEquivalentTo(cpuNewCores), + "coreFraction": Equal(cpuNewCoreFraction), }), }), "memory.size": MatchAllKeys(Keys{ @@ -748,13 +744,13 @@ var _ = Describe("Apply VM changes with manual approval", func() { }) }) -func CreateReadyVM(ctx context.Context, reconciler *two_phase_reconciler.ReconcilerCore[*controller.VMReconcilerState], reconcileExecutor *testutil.ReconcileExecutor, vm *virtv2.VirtualMachine, vmd *virtv2.VirtualMachineDisk) { +func CreateReadyVM(ctx context.Context, reconciler *two_phase_reconciler.ReconcilerCore[*controller.VMReconcilerState], reconcileExecutor *testutil.ReconcileExecutor, vm *virtv2.VirtualMachine, vmd *virtv2.VirtualDisk) { // Create Disk. err := reconciler.Client.Create(ctx, vmd) Expect(err).NotTo(HaveOccurred()) // Emulate CDI converge: set Ready status directly. - vmdObj, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmd.Name, Namespace: vmd.Namespace}, reconciler.Client, &virtv2.VirtualMachineDisk{}) + vmdObj, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmd.Name, Namespace: vmd.Namespace}, reconciler.Client, &virtv2.VirtualDisk{}) Expect(err).NotTo(HaveOccurred()) Expect(vmd).NotTo(BeNil()) vmdObj.Status.Phase = virtv2.DiskReady diff --git a/images/virtualization-artifact/pkg/controller/vm_webhook.go b/images/virtualization-artifact/pkg/controller/vm_webhook.go index f9d78fb5d..31e2af71f 100644 --- a/images/virtualization-artifact/pkg/controller/vm_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vm_webhook.go @@ -37,7 +37,7 @@ func (v *VMValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (a return nil, fmt.Errorf("expected a new VirtualMachine but got a %T", obj) } - v.log.Info("Validating VM", "spec.virtualMachineIPAddressClaimName", vm.Spec.VirtualMachineIPAddressClaimName) + v.log.Info("Validating VM", "spec.virtualMachineIPAddressClaim", vm.Spec.VirtualMachineIPAddressClaim) var warnings admission.Warnings @@ -64,8 +64,8 @@ func (v *VMValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime } v.log.Info("Validating VM", - "old.spec.virtualMachineIPAddressClaimName", oldVM.Spec.VirtualMachineIPAddressClaimName, - "new.spec.virtualMachineIPAddressClaimName", newVM.Spec.VirtualMachineIPAddressClaimName, + "old.spec.virtualMachineIPAddressClaim", oldVM.Spec.VirtualMachineIPAddressClaim, + "new.spec.virtualMachineIPAddressClaim", newVM.Spec.VirtualMachineIPAddressClaim, ) var warnings admission.Warnings @@ -142,7 +142,7 @@ func newIPAMVMValidator(ipam IPAM, client client.Client) *ipamVMValidator { } func (v *ipamVMValidator) validateCreate(ctx context.Context, vm *v1alpha2.VirtualMachine) (admission.Warnings, error) { - claimName := vm.Spec.VirtualMachineIPAddressClaimName + claimName := vm.Spec.VirtualMachineIPAddressClaim if claimName == "" { claimName = vm.Name } @@ -157,25 +157,25 @@ func (v *ipamVMValidator) validateCreate(ctx context.Context, vm *v1alpha2.Virtu return nil, nil } - if vm.Spec.VirtualMachineIPAddressClaimName == "" { + if vm.Spec.VirtualMachineIPAddressClaim == "" { return nil, fmt.Errorf("VirtualMachineIPAddressClaim with the name of the virtual machine"+ " already exists: explicitly specify the name of the VirtualMachineIPAddressClaim (%s)"+ - " in spec.virtualMachineIPAddressClaimName of virtual machine", claim.Name) + " in spec.virtualMachineIPAddressClaim of virtual machine", claim.Name) } return nil, v.ipam.CheckClaimAvailableForBinding(vm.Name, claim) } func (v *ipamVMValidator) validateUpdate(ctx context.Context, oldVM, newVM *v1alpha2.VirtualMachine) (admission.Warnings, error) { - if oldVM.Spec.VirtualMachineIPAddressClaimName == newVM.Spec.VirtualMachineIPAddressClaimName { + if oldVM.Spec.VirtualMachineIPAddressClaim == newVM.Spec.VirtualMachineIPAddressClaim { return nil, nil } - if newVM.Spec.VirtualMachineIPAddressClaimName == "" { - return nil, fmt.Errorf("spec.virtualMachineIPAddressClaimName cannot be changed to an empty value once set") + if newVM.Spec.VirtualMachineIPAddressClaim == "" { + return nil, fmt.Errorf("spec.virtualMachineIPAddressClaim cannot be changed to an empty value once set") } - claimKey := types.NamespacedName{Name: newVM.Spec.VirtualMachineIPAddressClaimName, Namespace: newVM.Namespace} + claimKey := types.NamespacedName{Name: newVM.Spec.VirtualMachineIPAddressClaim, Namespace: newVM.Namespace} claim, err := helper.FetchObject(ctx, claimKey, v.client, &v1alpha2.VirtualMachineIPAddressClaim{}) if err != nil { return nil, fmt.Errorf("unable to get VirtualMachineIPAddressClaim %s: %w", claimKey, err) diff --git a/images/virtualization-artifact/pkg/controller/vmbda_reconciler.go b/images/virtualization-artifact/pkg/controller/vmbda_reconciler.go index 67308b83e..31a600470 100644 --- a/images/virtualization-artifact/pkg/controller/vmbda_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/vmbda_reconciler.go @@ -76,14 +76,14 @@ func (r *VMBDAReconciler) Sync(ctx context.Context, _ reconcile.Request, state * // Do nothing if VM not found or not running. if state.VM == nil { - opts.Log.V(1).Info(fmt.Sprintf("VM %s is not created, do nothing", state.VMBDA.Current().Spec.VMName)) + opts.Log.V(1).Info(fmt.Sprintf("VM %s is not created, do nothing", state.VMBDA.Current().Spec.VirtualMachine)) state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) state.SetStatusFailure(virtv2.ReasonHotplugPostponed, "VM is missing") return nil } if state.VM.Status.Phase != virtv2.MachineRunning { - opts.Log.V(1).Info(fmt.Sprintf("VM %s is not running yet, do nothing", state.VMBDA.Current().Spec.VMName)) + opts.Log.V(1).Info(fmt.Sprintf("VM %s is not running yet, do nothing", state.VMBDA.Current().Spec.VirtualMachine)) state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) state.SetStatusFailure(virtv2.ReasonHotplugPostponed, "VM is not Running") return nil @@ -91,7 +91,7 @@ func (r *VMBDAReconciler) Sync(ctx context.Context, _ reconcile.Request, state * // Do nothing if VM not found or not running. if state.KVVMI == nil { - opts.Log.V(1).Info(fmt.Sprintf("KVVMI for VM %s is absent, do nothing", state.VMBDA.Current().Spec.VMName)) + opts.Log.V(1).Info(fmt.Sprintf("KVVMI for VM %s is absent, do nothing", state.VMBDA.Current().Spec.VirtualMachine)) state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) state.SetStatusFailure(virtv2.ReasonHotplugPostponed, "VM is missing") return nil @@ -99,7 +99,7 @@ func (r *VMBDAReconciler) Sync(ctx context.Context, _ reconcile.Request, state * // Do nothing if KVVMI is not running. if state.KVVMI.Status.Phase != virtv1.Running { - opts.Log.V(1).Info(fmt.Sprintf("KVVMI for VM %s is not running yet, do nothing", state.VMBDA.Current().Spec.VMName)) + opts.Log.V(1).Info(fmt.Sprintf("KVVMI for VM %s is not running yet, do nothing", state.VMBDA.Current().Spec.VirtualMachine)) state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) state.SetStatusFailure(virtv2.ReasonHotplugPostponed, "VM is not Running") return nil @@ -107,9 +107,9 @@ func (r *VMBDAReconciler) Sync(ctx context.Context, _ reconcile.Request, state * // Do nothing if VMD not found or not running. if state.VMD == nil || state.VMD.Status.Phase != virtv2.DiskReady { - opts.Log.V(1).Info("VMD is not ready yet, do nothing") + opts.Log.V(1).Info("virtual disk is not ready yet, do nothing") state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) - state.SetStatusFailure(virtv2.ReasonHotplugPostponed, "VMD is not ready") + state.SetStatusFailure(virtv2.ReasonHotplugPostponed, "virtual disk is not ready") return nil } @@ -142,7 +142,7 @@ func (r *VMBDAReconciler) Sync(ctx context.Context, _ reconcile.Request, state * } // Add attached device to the VM status. - if r.setVMStatusBlockDevicesAttached(blockDeviceIndex, state) { + if r.setVMStatusBlockDeviceRefs(blockDeviceIndex, state) { err = opts.Client.Status().Update(ctx, state.VM) if err != nil { return fmt.Errorf("failed to update VM status with hotplugged block device %s: %w", state.VMD.Name, err) @@ -161,11 +161,11 @@ func (r *VMBDAReconciler) Sync(ctx context.Context, _ reconcile.Request, state * if r.setVMHotpluggedFinalizer(state) { err := opts.Client.Update(ctx, state.VMD) if err != nil { - return fmt.Errorf("failed to set VMD finalizer with hotplugged block device %s: %w", state.VMD.Name, err) + return fmt.Errorf("failed to set virtual disk finalizer with hotplugged block device %s: %w", state.VMD.Name, err) } } - if r.setVMStatusBlockDevicesAttached(blockDeviceIndex, state) { + if r.setVMStatusBlockDeviceRefs(blockDeviceIndex, state) { err := opts.Client.Status().Update(ctx, state.VM) if err != nil { return fmt.Errorf("failed to update VM status with hotplugged block device %s: %w", state.VMD.Name, err) @@ -223,10 +223,11 @@ func isAttached(state *VMBDAReconcilerState) bool { // hotplugVolume requests kubevirt subresources APIService to attach volume to KVVMI. func (r *VMBDAReconciler) hotplugVolume(ctx context.Context, state *VMBDAReconcilerState) error { - if state.VMBDA.Current().Spec.BlockDevice.Type != virtv2.BlockDeviceAttachmentTypeVirtualMachineDisk { - return fmt.Errorf("unknown block device attachment type %s", state.VMBDA.Current().Spec.BlockDevice.Type) + if state.VMBDA.Current().Spec.BlockDeviceRef.Kind != virtv2.VMBDAObjectRefKindVirtualDisk { + return fmt.Errorf("unknown block device attachment kind %s", state.VMBDA.Current().Spec.BlockDeviceRef.Kind) } - name := kvbuilder.GenerateVMDDiskName(state.VMBDA.Current().Spec.BlockDevice.VirtualMachineDisk.Name) + + name := kvbuilder.GenerateVMDDiskName(state.VMBDA.Current().Spec.BlockDeviceRef.Name) hotplugRequest := virtv1.AddVolumeOptions{ Name: name, Disk: &virtv1.Disk{ @@ -236,7 +237,7 @@ func (r *VMBDAReconciler) hotplugVolume(ctx context.Context, state *VMBDAReconci Bus: "scsi", }, }, - Serial: state.VMBDA.Current().Spec.BlockDevice.VirtualMachineDisk.Name, + Serial: state.VMBDA.Current().Spec.BlockDeviceRef.Name, }, VolumeSource: &virtv1.HotplugVolumeSource{ PersistentVolumeClaim: &virtv1.PersistentVolumeClaimVolumeSource{ @@ -252,7 +253,7 @@ func (r *VMBDAReconciler) hotplugVolume(ctx context.Context, state *VMBDAReconci return err } kvApi := kvapi.New(state.Client, kv) - err = kvApi.AddVolume(ctx, state.VMBDA.Current().Namespace, state.VMBDA.Current().Spec.VMName, &hotplugRequest) + err = kvApi.AddVolume(ctx, state.VMBDA.Current().Namespace, state.VMBDA.Current().Spec.VirtualMachine, &hotplugRequest) if err != nil { return fmt.Errorf("error adding volume, %w", err) } @@ -262,11 +263,13 @@ func (r *VMBDAReconciler) hotplugVolume(ctx context.Context, state *VMBDAReconci // unplugVolume requests kubevirt subresources APIService to detach volume from KVVMI. func (r *VMBDAReconciler) unplugVolume(ctx context.Context, state *VMBDAReconcilerState) error { - if state.VMBDA.Current().Spec.BlockDevice.Type != virtv2.BlockDeviceAttachmentTypeVirtualMachineDisk { - return fmt.Errorf("unknown block device attachment type %s", state.VMBDA.Current().Spec.BlockDevice.Type) + if state.VMBDA.Current().Spec.BlockDeviceRef.Kind != virtv2.VMBDAObjectRefKindVirtualDisk { + return fmt.Errorf("unknown block device attachment type %s", state.VMBDA.Current().Spec.BlockDeviceRef.Kind) } + + name := kvbuilder.GenerateVMDDiskName(state.VMBDA.Current().Spec.BlockDeviceRef.Name) unplugRequest := virtv1.RemoveVolumeOptions{ - Name: kvbuilder.GenerateVMDDiskName(state.VMBDA.Current().Spec.BlockDevice.VirtualMachineDisk.Name), + Name: name, } kv, err := kubevirt.New(ctx, state.Client, r.controllerNamespace) @@ -274,7 +277,7 @@ func (r *VMBDAReconciler) unplugVolume(ctx context.Context, state *VMBDAReconcil return err } kvApi := kvapi.New(state.Client, kv) - err = kvApi.RemoveVolume(ctx, state.VMBDA.Current().Namespace, state.VMBDA.Current().Spec.VMName, &unplugRequest) + err = kvApi.RemoveVolume(ctx, state.VMBDA.Current().Namespace, state.VMBDA.Current().Spec.VirtualMachine, &unplugRequest) if err != nil { return fmt.Errorf("error removing volume, %w", err) } @@ -286,8 +289,8 @@ func (r *VMBDAReconciler) setVMHotpluggedFinalizer(state *VMBDAReconcilerState) return controllerutil.AddFinalizer(state.VMD, virtv2.FinalizerVMDProtection) } -// setVMStatusBlockDevicesAttached copy volume status from KVVMI for attached disk to the d8 VM block devices status. -func (r *VMBDAReconciler) setVMStatusBlockDevicesAttached(blockDeviceIndex int, state *VMBDAReconcilerState) bool { +// setVMStatusBlockDeviceRefs copy volume status from KVVMI for attached disk to the d8 VM block devices status. +func (r *VMBDAReconciler) setVMStatusBlockDeviceRefs(blockDeviceIndex int, state *VMBDAReconcilerState) bool { var vs virtv1.VolumeStatus for i := range state.KVVMI.Status.VolumeStatus { @@ -297,12 +300,12 @@ func (r *VMBDAReconciler) setVMStatusBlockDevicesAttached(blockDeviceIndex int, } if blockDeviceIndex > -1 { - blockDevice := state.VM.Status.BlockDevicesAttached[blockDeviceIndex] + blockDevice := state.VM.Status.BlockDeviceRefs[blockDeviceIndex] if blockDevice.Target != vs.Target || blockDevice.Size != state.VMD.Status.Capacity { blockDevice.Target = vs.Target blockDevice.Size = state.VMD.Status.Capacity - state.VM.Status.BlockDevicesAttached[blockDeviceIndex] = blockDevice + state.VM.Status.BlockDeviceRefs[blockDeviceIndex] = blockDevice return true } @@ -310,11 +313,9 @@ func (r *VMBDAReconciler) setVMStatusBlockDevicesAttached(blockDeviceIndex int, return false } - state.VM.Status.BlockDevicesAttached = append(state.VM.Status.BlockDevicesAttached, virtv2.BlockDeviceStatus{ - Type: virtv2.DiskDevice, - VirtualMachineDisk: &virtv2.DiskDeviceSpec{ - Name: state.VMD.Name, - }, + state.VM.Status.BlockDeviceRefs = append(state.VM.Status.BlockDeviceRefs, virtv2.BlockDeviceStatusRef{ + Kind: virtv2.DiskDevice, + Name: state.VMD.Name, Target: vs.Target, Size: state.VMD.Status.Capacity, Hotpluggable: true, @@ -334,17 +335,16 @@ func (r *VMBDAReconciler) checkHotplugSanity(state *VMBDAReconcilerState) (strin var messages []string // Check if disk is already in the spec of VM. - diskName := state.VMBDA.Current().Spec.BlockDevice.VirtualMachineDisk.Name + diskName := state.VMBDA.Current().Spec.BlockDeviceRef.Name - for _, bd := range state.VM.Spec.BlockDevices { - disk := bd.VirtualMachineDisk - if disk != nil && disk.Name == diskName { - messages = append(messages, fmt.Sprintf("disk %s is already attached to VM", diskName)) + for _, bd := range state.VM.Spec.BlockDeviceRefs { + if bd.Kind == virtv2.DiskDevice && bd.Name == diskName { + messages = append(messages, fmt.Sprintf("disk %s is already attached to virtual machine", diskName)) break } } if len(state.VM.Status.RestartAwaitingChanges) > 0 { - messages = append(messages, "vm waits for restart approval") + messages = append(messages, "virtual machine waits for restart approval") } if len(messages) == 0 { diff --git a/images/virtualization-artifact/pkg/controller/vmbda_reconciler_state.go b/images/virtualization-artifact/pkg/controller/vmbda_reconciler_state.go index cf43f95ec..df18d3e9e 100644 --- a/images/virtualization-artifact/pkg/controller/vmbda_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/vmbda_reconciler_state.go @@ -22,7 +22,7 @@ type VMBDAReconcilerState struct { VM *virtv2.VirtualMachine KVVMI *virtv1.VirtualMachineInstance - VMD *virtv2.VirtualMachineDisk + VMD *virtv2.VirtualDisk PVC *corev1.PersistentVolumeClaim Result *reconcile.Result @@ -83,37 +83,37 @@ func (state *VMBDAReconcilerState) Reload(ctx context.Context, req reconcile.Req return nil } - vmKey := types.NamespacedName{Name: state.VMBDA.Current().Spec.VMName, Namespace: state.VMBDA.Current().Namespace} + vmKey := types.NamespacedName{Name: state.VMBDA.Current().Spec.VirtualMachine, Namespace: state.VMBDA.Current().Namespace} state.VM, err = helper.FetchObject(ctx, vmKey, client, &virtv2.VirtualMachine{}) if err != nil { return fmt.Errorf("unable to get VM %s: %w", vmKey, err) } - kvvmiKey := types.NamespacedName{Name: state.VMBDA.Current().Spec.VMName, Namespace: state.VMBDA.Current().Namespace} + kvvmiKey := types.NamespacedName{Name: state.VMBDA.Current().Spec.VirtualMachine, Namespace: state.VMBDA.Current().Namespace} state.KVVMI, err = helper.FetchObject(ctx, kvvmiKey, client, &virtv1.VirtualMachineInstance{}) if err != nil { return fmt.Errorf("unable to get KVVMI %s: %w", kvvmiKey, err) } - switch state.VMBDA.Current().Spec.BlockDevice.Type { - case virtv2.BlockDeviceAttachmentTypeVirtualMachineDisk: - vmdKey := types.NamespacedName{Name: state.VMBDA.Current().Spec.BlockDevice.VirtualMachineDisk.Name, Namespace: state.VMBDA.Current().Namespace} - state.VMD, err = helper.FetchObject(ctx, vmdKey, client, &virtv2.VirtualMachineDisk{}) + switch state.VMBDA.Current().Spec.BlockDeviceRef.Kind { + case virtv2.VMBDAObjectRefKindVirtualDisk: + vmdKey := types.NamespacedName{Name: state.VMBDA.Current().Spec.BlockDeviceRef.Name, Namespace: state.VMBDA.Current().Namespace} + state.VMD, err = helper.FetchObject(ctx, vmdKey, client, &virtv2.VirtualDisk{}) if err != nil { - return fmt.Errorf("unable to get VMD %s: %w", vmdKey, err) + return fmt.Errorf("unable to get virtual disk %s: %w", vmdKey, err) } if state.VMD == nil { return nil } - pvcKey := types.NamespacedName{Name: state.VMD.Status.Target.PersistentVolumeClaimName, Namespace: state.VMBDA.Current().Namespace} + pvcKey := types.NamespacedName{Name: state.VMD.Status.Target.PersistentVolumeClaim, Namespace: state.VMBDA.Current().Namespace} state.PVC, err = helper.FetchObject(ctx, pvcKey, client, &corev1.PersistentVolumeClaim{}) if err != nil { return fmt.Errorf("unable to get PVC %s: %w", pvcKey, err) } default: - return fmt.Errorf("unknown block device attachment type %s", state.VMBDA.Current().Spec.VMName) + return fmt.Errorf("unknown block device attachment type %s", state.VMBDA.Current().Spec.BlockDeviceRef.Kind) } return nil @@ -132,15 +132,15 @@ func (state *VMBDAReconcilerState) IndexVMStatusBDA() int { return -1 } - for i, blockDevice := range state.VM.Status.BlockDevicesAttached { - if blockDevice.VirtualMachineDisk != nil && blockDevice.VirtualMachineDisk.Name == state.VMD.Name { + for i, bda := range state.VM.Status.BlockDeviceRefs { + if bda.Kind == virtv2.DiskDevice && bda.Name == state.VMD.Name { return i } } return -1 } -// RemoveVMStatusBDA removes device from VM.Status.BlockDevicesAttached by its name. +// RemoveVMStatusBDA removes device from VM.Status.BlockDeviceRefs by its name. func (state *VMBDAReconcilerState) RemoveVMStatusBDA() bool { if state.VM == nil { return false @@ -151,9 +151,9 @@ func (state *VMBDAReconcilerState) RemoveVMStatusBDA() bool { return false } - state.VM.Status.BlockDevicesAttached = append( - state.VM.Status.BlockDevicesAttached[:blockDeviceIndex], - state.VM.Status.BlockDevicesAttached[blockDeviceIndex+1:]..., + state.VM.Status.BlockDeviceRefs = append( + state.VM.Status.BlockDeviceRefs[:blockDeviceIndex], + state.VM.Status.BlockDeviceRefs[blockDeviceIndex+1:]..., ) return true diff --git a/images/virtualization-artifact/pkg/controller/vmbda_webhook.go b/images/virtualization-artifact/pkg/controller/vmbda_webhook.go index 999c77c02..6d349de3b 100644 --- a/images/virtualization-artifact/pkg/controller/vmbda_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vmbda_webhook.go @@ -28,13 +28,13 @@ func (v *VMBDAValidator) ValidateCreate(_ context.Context, obj runtime.Object) ( v.log.Info("Validating VMBDA") - switch vmbda.Spec.BlockDevice.Type { - case v1alpha2.BlockDeviceAttachmentTypeVirtualMachineDisk: - if vmbda.Spec.BlockDevice.VirtualMachineDisk == nil || vmbda.Spec.BlockDevice.VirtualMachineDisk.Name == "" { - return nil, errors.New("virtual machine disk name is omitted, but required") + switch vmbda.Spec.BlockDeviceRef.Kind { + case v1alpha2.VMBDAObjectRefKindVirtualDisk: + if vmbda.Spec.BlockDeviceRef.Name == "" { + return nil, errors.New("virtual disk name is omitted, but required") } default: - return nil, fmt.Errorf("unknown block device type %q", vmbda.Spec.BlockDevice.Type) + return nil, fmt.Errorf("unknown block device kind %q", vmbda.Spec.BlockDeviceRef.Kind) } return nil, nil @@ -53,21 +53,21 @@ func (v *VMBDAValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtim v.log.Info("Validating VMBDA") - if newVMBDA.Spec.VMName != oldVMBDA.Spec.VMName { + if newVMBDA.Spec.VirtualMachine != oldVMBDA.Spec.VirtualMachine { return nil, errors.New("virtual machine name cannot be changed once set") } - if newVMBDA.Spec.BlockDevice.Type != oldVMBDA.Spec.BlockDevice.Type { + if newVMBDA.Spec.BlockDeviceRef.Kind != oldVMBDA.Spec.BlockDeviceRef.Kind { return nil, errors.New("block device type cannot be changed once set") } - switch newVMBDA.Spec.BlockDevice.Type { - case v1alpha2.BlockDeviceAttachmentTypeVirtualMachineDisk: - if newVMBDA.Spec.BlockDevice.VirtualMachineDisk == nil || newVMBDA.Spec.BlockDevice.VirtualMachineDisk.Name != oldVMBDA.Spec.BlockDevice.VirtualMachineDisk.Name { - return nil, errors.New("virtual machine disk name cannot be changed once set") + switch newVMBDA.Spec.BlockDeviceRef.Kind { + case v1alpha2.VMBDAObjectRefKindVirtualDisk: + if newVMBDA.Spec.BlockDeviceRef.Name != oldVMBDA.Spec.BlockDeviceRef.Name { + return nil, errors.New("virtual disk name cannot be changed once set") } default: - return nil, fmt.Errorf("unknown block device type %q", newVMBDA.Spec.BlockDevice.Type) + return nil, fmt.Errorf("unknown block device kind %q", newVMBDA.Spec.BlockDeviceRef.Kind) } return nil, nil diff --git a/images/virtualization-artifact/pkg/controller/vmchange/comparator_block_devices.go b/images/virtualization-artifact/pkg/controller/vmchange/comparator_block_devices.go index f59813f35..72e0a0bc7 100644 --- a/images/virtualization-artifact/pkg/controller/vmchange/comparator_block_devices.go +++ b/images/virtualization-artifact/pkg/controller/vmchange/comparator_block_devices.go @@ -7,18 +7,18 @@ import ( "github.com/deckhouse/virtualization/api/core/v1alpha2" ) -const BlockDevicesPath = "blockDevices" +const BlockDevicesPath = "blockDeviceRefs" // compareBlockDevices returns changes between current and desired blockDevices lists. func compareBlockDevices(current, desired *v1alpha2.VirtualMachineSpec) []FieldChange { - if len(current.BlockDevices) == 0 && len(desired.BlockDevices) == 0 { + if len(current.BlockDeviceRefs) == 0 && len(desired.BlockDeviceRefs) == 0 { return nil } fullChanges := compareEmpty( BlockDevicesPath, - NewValue(current.BlockDevices, len(current.BlockDevices) == 0, false), - NewValue(desired.BlockDevices, len(desired.BlockDevices) == 0, false), + NewValue(current.BlockDeviceRefs, len(current.BlockDeviceRefs) == 0, false), + NewValue(desired.BlockDeviceRefs, len(desired.BlockDeviceRefs) == 0, false), ActionRestart, ) @@ -68,30 +68,30 @@ func compareBlockDevices(current, desired *v1alpha2.VirtualMachineSpec) []FieldC changes = append(changes, FieldChange{ Operation: ChangeReplace, Path: itemPath, - CurrentValue: current.BlockDevices[idx], - DesiredValue: desired.BlockDevices[idx], + CurrentValue: current.BlockDeviceRefs[idx], + DesiredValue: desired.BlockDeviceRefs[idx], ActionRequired: ActionRestart, }) case isAdded: changes = append(changes, FieldChange{ Operation: ChangeAdd, Path: itemPath, - DesiredValue: desired.BlockDevices[idx], + DesiredValue: desired.BlockDeviceRefs[idx], ActionRequired: ActionRestart, }) case isRemoved: changes = append(changes, FieldChange{ Operation: ChangeRemove, Path: itemPath, - CurrentValue: current.BlockDevices[idx], + CurrentValue: current.BlockDeviceRefs[idx], ActionRequired: ActionRestart, }) case isSwapped: changes = append(changes, FieldChange{ Operation: ChangeReplace, Path: itemPath, - CurrentValue: current.BlockDevices[idx], - DesiredValue: desired.BlockDevices[idx], + CurrentValue: current.BlockDeviceRefs[idx], + DesiredValue: desired.BlockDeviceRefs[idx], ActionRequired: ActionRestart, }) } @@ -102,9 +102,9 @@ func compareBlockDevices(current, desired *v1alpha2.VirtualMachineSpec) []FieldC func cvmiIndexedNames(vm *v1alpha2.VirtualMachineSpec) map[string]int { res := make(map[string]int) - for idx, dev := range vm.BlockDevices { - if dev.ClusterVirtualMachineImage != nil { - res[dev.ClusterVirtualMachineImage.Name] = idx + for idx, dev := range vm.BlockDeviceRefs { + if dev.Kind == v1alpha2.ClusterImageDevice { + res[dev.Name] = idx } } return res @@ -112,9 +112,9 @@ func cvmiIndexedNames(vm *v1alpha2.VirtualMachineSpec) map[string]int { func vmiIndexedNames(vm *v1alpha2.VirtualMachineSpec) map[string]int { res := make(map[string]int) - for idx, dev := range vm.BlockDevices { - if dev.VirtualMachineImage != nil { - res[dev.VirtualMachineImage.Name] = idx + for idx, dev := range vm.BlockDeviceRefs { + if dev.Kind == v1alpha2.VirtualImageKind { + res[dev.Name] = idx } } return res @@ -122,9 +122,9 @@ func vmiIndexedNames(vm *v1alpha2.VirtualMachineSpec) map[string]int { func vmdIndexedNames(vm *v1alpha2.VirtualMachineSpec) map[string]int { res := make(map[string]int) - for idx, dev := range vm.BlockDevices { - if dev.VirtualMachineDisk != nil { - res[dev.VirtualMachineDisk.Name] = idx + for idx, dev := range vm.BlockDeviceRefs { + if dev.Kind == v1alpha2.VirtualDiskKind { + res[dev.Name] = idx } } return res diff --git a/images/virtualization-artifact/pkg/controller/vmchange/comparators.go b/images/virtualization-artifact/pkg/controller/vmchange/comparators.go index 1e1bdea59..3ebf6fda7 100644 --- a/images/virtualization-artifact/pkg/controller/vmchange/comparators.go +++ b/images/virtualization-artifact/pkg/controller/vmchange/comparators.go @@ -25,11 +25,11 @@ func compareRunPolicy(current, desired *v1alpha2.VirtualMachineSpec) []FieldChan ) } -func compareVirtualMachineIPAddressClaimName(current, desired *v1alpha2.VirtualMachineSpec) []FieldChange { +func compareVirtualMachineIPAddressClaim(current, desired *v1alpha2.VirtualMachineSpec) []FieldChange { return compareStrings( - "virtualMachineIPAddressClaimName", - current.VirtualMachineIPAddressClaimName, - desired.VirtualMachineIPAddressClaimName, + "virtualMachineIPAddressClaim", + current.VirtualMachineIPAddressClaim, + desired.VirtualMachineIPAddressClaim, "", ActionNone, ) @@ -123,7 +123,7 @@ func compareCPU(current, desired *v1alpha2.VirtualMachineSpec) []FieldChange { return fractionChanges } - modelChanges := compareStrings("cpu.model", current.CPU.ModelName, desired.CPU.ModelName, DefaultCPUModelName, ActionRestart) + modelChanges := compareStrings("cpu.virtualMachineCPUModel", current.CPU.VirtualMachineCPUModel, desired.CPU.VirtualMachineCPUModel, DefaultCPUModelName, ActionRestart) if HasChanges(modelChanges) { return modelChanges } @@ -160,11 +160,11 @@ func compareProvisioning(current, desired *v1alpha2.VirtualMachineSpec) []FieldC } } - if current.Provisioning.Type == v1alpha2.ProvisioningTypeSysprepSecret { - currentSecret := current.Provisioning.SysprepSecretRef - desiredSecret := desired.Provisioning.SysprepSecretRef + if current.Provisioning.Type == v1alpha2.ProvisioningTypeSysprepRef { + currentSecret := current.Provisioning.SysprepRef + desiredSecret := desired.Provisioning.SysprepRef changes = compareEmpty( - "provisioning.sysprepSecretRef", + "provisioning.sysprepRef", NewPtrValue(currentSecret, currentSecret == nil), NewPtrValue(desiredSecret, desiredSecret == nil), ActionRestart, @@ -173,9 +173,21 @@ func compareProvisioning(current, desired *v1alpha2.VirtualMachineSpec) []FieldC return changes } - // SysprepSecretRef is not nil, compare names. + // SysprepRef is not nil, compare kinds. + changes = compareStrings( + "provisioning.sysprepRef.kind", + string(currentSecret.Kind), + string(desiredSecret.Kind), + "", + ActionRestart, + ) + if len(changes) > 0 { + return changes + } + + // SysprepRef is not nil, compare names. return compareStrings( - "provisioning.sysprepSecretRef.name", + "provisioning.sysprepRef.name", currentSecret.Name, desiredSecret.Name, "", @@ -193,11 +205,11 @@ func compareProvisioning(current, desired *v1alpha2.VirtualMachineSpec) []FieldC ) } - if current.Provisioning.Type == v1alpha2.ProvisioningTypeUserDataSecret { - currentSecret := current.Provisioning.UserDataSecretRef - desiredSecret := desired.Provisioning.UserDataSecretRef + if current.Provisioning.Type == v1alpha2.ProvisioningTypeUserDataRef { + currentSecret := current.Provisioning.UserDataRef + desiredSecret := desired.Provisioning.UserDataRef changes = compareEmpty( - "provisioning.userDataSecretRef", + "provisioning.userDataRef", NewPtrValue(currentSecret, currentSecret == nil), NewPtrValue(desiredSecret, desiredSecret == nil), ActionRestart, @@ -206,9 +218,21 @@ func compareProvisioning(current, desired *v1alpha2.VirtualMachineSpec) []FieldC return changes } + // UserDataSecretRef is not nil, compare kinds. + changes = compareStrings( + "provisioning.userDataRef.kind", + string(currentSecret.Kind), + string(desiredSecret.Kind), + "", + ActionRestart, + ) + if len(changes) > 0 { + return changes + } + // UserDataSecretRef is not nil, compare names. return compareStrings( - "provisioning.userDataSecretRef.name", + "provisioning.userDataRef.name", currentSecret.Name, desiredSecret.Name, "", diff --git a/images/virtualization-artifact/pkg/controller/vmchange/compare.go b/images/virtualization-artifact/pkg/controller/vmchange/compare.go index 1ee34b3ca..a1b276033 100644 --- a/images/virtualization-artifact/pkg/controller/vmchange/compare.go +++ b/images/virtualization-artifact/pkg/controller/vmchange/compare.go @@ -8,7 +8,7 @@ type SpecFieldsComparator func(prev, next *v1alpha2.VirtualMachineSpec) []FieldC var specComparators = []SpecFieldsComparator{ compareRunPolicy, - compareVirtualMachineIPAddressClaimName, + compareVirtualMachineIPAddressClaim, compareTopologySpreadConstraints, compareAffinity, compareNodeSelector, diff --git a/images/virtualization-artifact/pkg/controller/vmchange/compare_test.go b/images/virtualization-artifact/pkg/controller/vmchange/compare_test.go index 5cee09ec3..a99732453 100644 --- a/images/virtualization-artifact/pkg/controller/vmchange/compare_test.go +++ b/images/virtualization-artifact/pkg/controller/vmchange/compare_test.go @@ -114,147 +114,125 @@ memory: ), }, { - "restart on blockDevices section add", + "restart on blockDeviceRefs section add", ``, ` -blockDevices: -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualImage + name: linux `, assertChanges( actionRequired(ActionRestart), - requirePathOperation("blockDevices", ChangeAdd), + requirePathOperation("blockDeviceRefs", ChangeAdd), ), }, { - "restart on blockDevices section remove", + "restart on blockDeviceRefs section remove", ` -blockDevices: -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualImage + name: linux `, ``, assertChanges( actionRequired(ActionRestart), - requirePathOperation("blockDevices", ChangeRemove), + requirePathOperation("blockDeviceRefs", ChangeRemove), ), }, { - "restart on blockDevices add disk", + "restart on blockDeviceRefs add disk", ` -blockDevices: -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualImage + name: linux `, ` -blockDevices: -- type: VirtualMachineDisk - virtualMachineDisk: - name: linux -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualDisk + name: linux +- kind: VirtualImage + name: linux `, assertChanges( actionRequired(ActionRestart), - requirePathOperation("blockDevices.0", ChangeAdd), + requirePathOperation("blockDeviceRefs.0", ChangeAdd), ), }, { - "restart on blockDevices remove disk", + "restart on blockDeviceRefs remove disk", ` -blockDevices: -- type: VirtualMachineDisk - virtualMachineDisk: - name: linux -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualDisk + name: linux +- kind: VirtualImage + name: linux `, ` -blockDevices: -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualImage + name: linux `, assertChanges( actionRequired(ActionRestart), - requirePathOperation("blockDevices.0", ChangeRemove), + requirePathOperation("blockDeviceRefs.0", ChangeRemove), ), }, { - "restart on blockDevices change order", + "restart on blockDeviceRefs change order", ` -blockDevices: -- type: VirtualMachineImage - virtualMachineImage: - name: linux -- type: VirtualMachineDisk - virtualMachineDisk: - name: linux +blockDeviceRefs: +- kind: VirtualImage + name: linux +- kind: VirtualDisk + name: linux `, ` -blockDevices: -- type: VirtualMachineDisk - virtualMachineDisk: - name: linux -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualDisk + name: linux +- kind: VirtualImage + name: linux `, assertChanges( actionRequired(ActionRestart), - requirePathOperation("blockDevices.0", ChangeReplace), - requirePathOperation("blockDevices.1", ChangeReplace), + requirePathOperation("blockDeviceRefs.0", ChangeReplace), + requirePathOperation("blockDeviceRefs.1", ChangeReplace), ), }, { - "restart on blockDevices change order :: bigger", - ` -blockDevices: -- type: VirtualMachineImage - virtualMachineImage: - name: linux -- type: VirtualMachineDisk - virtualMachineDisk: - name: linux -- type: ClusterVirtualMachineImage - virtualMachineImage: - name: ubuntu -- type: VirtualMachineDisk - virtualMachineDisk: - name: main -- type: VirtualMachineDisk - virtualMachineDisk: - name: data + "restart on blockDeviceRefs change order :: bigger", + ` +blockDeviceRefs: +- kind: VirtualImage + name: linux +- kind: VirtualDisk + name: linux +- kind: ClusterVirtualImage + name: ubuntu +- kind: VirtualDisk + name: main +- kind: VirtualDisk + name: data `, // Change order: 12345 -> 25341 ` -blockDevices: -- type: VirtualMachineDisk - virtualMachineDisk: - name: linux -- type: VirtualMachineDisk - virtualMachineDisk: - name: data -- type: ClusterVirtualMachineImage - virtualMachineImage: - name: ubuntu -- type: VirtualMachineDisk - virtualMachineDisk: - name: main -- type: VirtualMachineImage - virtualMachineImage: - name: linux +blockDeviceRefs: +- kind: VirtualDisk + name: linux +- kind: VirtualDisk + name: data +- kind: ClusterVirtualImage + name: ubuntu +- kind: VirtualDisk + name: main +- kind: VirtualImage + name: linux `, assertChanges( actionRequired(ActionRestart), - requirePathOperation("blockDevices.0", ChangeReplace), - requirePathOperation("blockDevices.1", ChangeReplace), - requirePathOperation("blockDevices.4", ChangeReplace), + requirePathOperation("blockDeviceRefs.0", ChangeReplace), + requirePathOperation("blockDeviceRefs.1", ChangeReplace), + requirePathOperation("blockDeviceRefs.4", ChangeReplace), ), }, { @@ -276,8 +254,9 @@ provisioning: "restart on provisioning remove", ` provisioning: - type: UserDataSecret - userDataSecretRef: + type: UserDataRef + userDataRef: + kind: Secret name: cloud-init-secret `, "", @@ -290,8 +269,9 @@ provisioning: "restart on provisioning type change", ` provisioning: - type: UserDataSecret - userDataSecretRef: + type: UserDataRef + userDataRef: + kind: Secret name: cloud-init-secret `, ` @@ -309,19 +289,21 @@ provisioning: "restart on provisioning secretref name change", ` provisioning: - type: UserDataSecret - userDataSecretRef: + type: UserDataRef + userDataRef: + kind: Secret name: cloud-init-secret `, ` provisioning: - type: UserDataSecret - userDataSecretRef: + type: UserDataRef + userDataRef: + kind: Secret name: provisioning-secret `, assertChanges( actionRequired(ActionRestart), - requirePathOperation("provisioning.userDataSecretRef.name", ChangeReplace), + requirePathOperation("provisioning.userDataRef.name", ChangeReplace), ), }, { diff --git a/images/virtualization-artifact/pkg/controller/vmchange/spec_changes.go b/images/virtualization-artifact/pkg/controller/vmchange/spec_changes.go index 9c4154911..73f5c637c 100644 --- a/images/virtualization-artifact/pkg/controller/vmchange/spec_changes.go +++ b/images/virtualization-artifact/pkg/controller/vmchange/spec_changes.go @@ -85,14 +85,14 @@ const NoChanges = "NoChanges" // current spec: // // blockDevices: -// - type: ClusterVirtualMachineImage -// clusterVirtualMachineImage: {name: linux-ubuntu} +// - type: ClusterVirtualImage +// clusterVirtualImage: {name: linux-ubuntu} // // desired spec: // // blockDevices: -// - type: VirtualMachineImage -// virtualMachineImage: {name: jammy-ubuntu} +// - type: VirtualImage +// virtualImage: {name: jammy-ubuntu} // // status: // @@ -100,28 +100,28 @@ const NoChanges = "NoChanges" // - op: replace // path: blockDevices.0 // currentValue: -// type: ClusterVirtualMachineImage -// clusterVirtualMachineImage: {name: linux-ubuntu} +// type: ClusterVirtualImage +// clusterVirtualImage: {name: linux-ubuntu} // desiredValue: -// type: VirtualMachineImage -// virtualMachineImage: {name: jammy-ubuntu} +// type: VirtualImage +// virtualImage: {name: jammy-ubuntu} // // Remove, add block devices. // current spec: // // blockDevices: -// - type: ClusterVirtualMachineImage -// clusterVirtualMachineImage: {name: linux-ubuntu} -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk} +// - type: ClusterVirtualImage +// clusterVirtualImage: {name: linux-ubuntu} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk} // // desired spec: // // blockDevices: -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk} -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk-data} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk-data} // // status: // @@ -129,39 +129,39 @@ const NoChanges = "NoChanges" // - operation: remove // path: blockDevices.0 // currentValue: -// type: ClusterVirtualMachineImage -// clusterVirtualMachineImage: {name: linux-ubuntu} +// type: ClusterVirtualImage +// clusterVirtualImage: {name: linux-ubuntu} // - operation: add // path: blockDevices.1 // desiredValue: -// type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk-data} +// type: VirtualDisk +// virtualDisk: {name: vm-disk-data} // // Multiple operations: remove, add, change order. // Operations are compacted by index: // current spec: // // blockDevices: -// - type: ClusterVirtualMachineImage -// clusterVirtualMachineImage: {name: linux-ubuntu} -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk} -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk-big} -// - type: VirtualMachineImage -// virtualMachineImage: {name: jammy-ubuntu} +// - type: ClusterVirtualImage +// clusterVirtualImage: {name: linux-ubuntu} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk-big} +// - type: VirtualImage +// virtualImage: {name: jammy-ubuntu} // // desired spec: // // blockDevices: -// - type: VirtualMachineImage -// virtualMachineImage: {name: jammy-ubuntu} -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk-2} -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk-big} <-- the only disk saves its index. -// - type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk} +// - type: VirtualImage +// virtualImage: {name: jammy-ubuntu} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk-2} +// - type: VirtualDisk +// virtualDisk: {name: vm-disk-big} <-- the only disk saves its index. +// - type: VirtualDisk +// virtualDisk: {name: vm-disk} // // status: // @@ -169,27 +169,27 @@ const NoChanges = "NoChanges" // - operation: replace // path: blockDevices.0 // currentValue: -// type: ClusterVirtualMachineImage -// clusterVirtualMachineImage: {name: linux-ubuntu} +// type: ClusterVirtualImage +// clusterVirtualImage: {name: linux-ubuntu} // desiredValue: -// type: VirtualMachineImage -// virtualMachineImage: {name: jammy-ubuntu} +// type: VirtualImage +// virtualImage: {name: jammy-ubuntu} // - operation: replace // path: blockDevices.1 // currentValue: -// type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk} +// type: VirtualDisk +// virtualDisk: {name: vm-disk} // desiredValue: -// type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk-2} +// type: VirtualDisk +// virtualDisk: {name: vm-disk-2} // - operation: replace // path: blockDevices.3 // currentValue: -// type: VirtualMachineImage -// virtualMachineImage: {name: jammy-ubuntu} +// type: VirtualImage +// virtualImage: {name: jammy-ubuntu} // desiredValue: -// type: VirtualMachineDisk -// virtualMachineDisk: {name: vm-disk} +// type: VirtualDisk +// virtualDisk: {name: vm-disk} type SpecChanges struct { changes []FieldChange } diff --git a/images/virtualization-artifact/pkg/controller/vmd_controller.go b/images/virtualization-artifact/pkg/controller/vmd_controller.go index 309663d03..db86d820d 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_controller.go +++ b/images/virtualization-artifact/pkg/controller/vmd_controller.go @@ -19,8 +19,8 @@ import ( ) const ( - vmdControllerName = "vmd-controller" - vmdShortName = "vmd" + vmdControllerName = "vd-controller" + vmdShortName = "vd" ) func NewVMDController( @@ -63,7 +63,7 @@ func NewVMDController( } if err = builder.WebhookManagedBy(mgr). - For(&v1alpha2.VirtualMachineDisk{}). + For(&v1alpha2.VirtualDisk{}). WithValidator(NewVMDValidator(log)). Complete(); err != nil { return nil, err @@ -71,7 +71,7 @@ func NewVMDController( diskmetrics.SetupCollector(&diskLister{diskCache: mgrCache}, metrics.Registry) - log.Info("Initialized VirtualMachineDisk controller") + log.Info("Initialized VirtualDisk controller") return c, nil } @@ -79,8 +79,8 @@ type diskLister struct { diskCache cache.Cache } -func (l diskLister) List() ([]v1alpha2.VirtualMachineDisk, error) { - disks := v1alpha2.VirtualMachineDiskList{} +func (l diskLister) List() ([]v1alpha2.VirtualDisk, error) { + disks := v1alpha2.VirtualDiskList{} err := l.diskCache.List(context.Background(), &disks) if err != nil { return nil, err diff --git a/images/virtualization-artifact/pkg/controller/vmd_datavolume.go b/images/virtualization-artifact/pkg/controller/vmd_datavolume.go index d3c6088f0..61984c797 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_datavolume.go +++ b/images/virtualization-artifact/pkg/controller/vmd_datavolume.go @@ -24,12 +24,12 @@ var ( ErrPVCSizeSmallerImageVirtualSize = errors.New("persistentVolumeClaim size is smaller than image virtual size") ) -func (r *VMDReconciler) getPVCSize(vmd *virtv2.VirtualMachineDisk, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) (resource.Quantity, error) { +func (r *VMDReconciler) getPVCSize(vmd *virtv2.VirtualDisk, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) (resource.Quantity, error) { pvcSize := vmd.Spec.PersistentVolumeClaim.Size if vmdutil.IsBlankPVC(vmd) { if pvcSize == nil || pvcSize.IsZero() { - return resource.Quantity{}, errors.New("spec.persistentVolumeClaim.size should be set for blank VMD") + return resource.Quantity{}, errors.New("spec.persistentVolumeClaim.size should be set for blank virtual disk") } return *pvcSize, nil @@ -78,7 +78,7 @@ func (r *VMDReconciler) getPVCSize(vmd *virtv2.VirtualMachineDisk, state *VMDRec } // createDataVolume creates DataVolume resource to copy image from DVCR to PVC. -func (r *VMDReconciler) createDataVolume(ctx context.Context, vmd *virtv2.VirtualMachineDisk, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { +func (r *VMDReconciler) createDataVolume(ctx context.Context, vmd *virtv2.VirtualDisk, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { // Retrieve PVC size. pvcSize, err := r.getPVCSize(vmd, state, opts) if err != nil { @@ -87,14 +87,14 @@ func (r *VMDReconciler) createDataVolume(ctx context.Context, vmd *virtv2.Virtua dv, err := r.makeDataVolumeFromVMD(state, state.Supplements.DataVolume(), pvcSize) if err != nil { - return fmt.Errorf("apply VMD spec to DataVolume: %w", err) + return fmt.Errorf("apply virtual disk spec to DataVolume: %w", err) } opts.Log.V(2).Info(fmt.Sprintf("DV gvk before Create: %s", dv.GetObjectKind().GroupVersionKind().String())) if err = opts.Client.Create(ctx, dv); err != nil { opts.Log.V(2).Info("Error create new DV spec", "dv.spec", dv.Spec) - return fmt.Errorf("create DataVolume/%s for VMD/%s: %w", dv.GetName(), vmd.GetName(), err) + return fmt.Errorf("create DataVolume/%s for VD/%s: %w", dv.GetName(), vmd.GetName(), err) } opts.Log.Info("Created new DV", "dv.name", dv.GetName()) opts.Log.V(2).Info("Created new DV spec", "dv.spec", dv.Spec, "dv.gvk", dv.GetObjectKind().GroupVersionKind()) @@ -132,20 +132,28 @@ func (r *VMDReconciler) makeDataVolumeFromVMD(state *VMDReconcilerState, dvName // Use DV name for the Secret with DVCR auth and the ConfigMap with DVCR CA Bundle. dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMD(vmd.Name, vmd.Namespace) dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) - case ds != nil && ds.Type == virtv2.DataSourceTypeClusterVirtualMachineImage: - dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ClusterVirtualMachineImage.Name) - dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) - case ds != nil && ds.Type == virtv2.DataSourceTypeVirtualMachineImage: - vmiRef := ds.VirtualMachineImage - dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(vmiRef.Name, vmd.Namespace) - dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) + case ds != nil && ds.Type == virtv2.DataSourceTypeObjectRef: + if ds.ObjectRef == nil { + return nil, fmt.Errorf("nil objectRef %q", vmdutil.GetDataSourceType(vmd)) + } + + switch ds.ObjectRef.Kind { + case virtv2.VirtualDiskObjectRefKindVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(ds.ObjectRef.Name, vmd.Namespace) + dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) + case virtv2.VirtualDiskObjectRefKindClusterVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ObjectRef.Name) + dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) + default: + return nil, fmt.Errorf("unsupported object ref kind %q", ds.ObjectRef.Kind) + } case vmdutil.IsBlankPVC(vmd): dvBuilder.SetBlankDataSource() default: return nil, fmt.Errorf("unsupported dataSource type %q", vmdutil.GetDataSourceType(vmd)) } - dvBuilder.SetPVC(vmd.Spec.PersistentVolumeClaim.StorageClassName, pvcSize) + dvBuilder.SetPVC(vmd.Spec.PersistentVolumeClaim.StorageClass, pvcSize) dvBuilder.SetOwnerRef(vmd, vmd.GetObjectKind().GroupVersionKind()) dvBuilder.AddFinalizer(virtv2.FinalizerDVProtection) diff --git a/images/virtualization-artifact/pkg/controller/vmd_importer.go b/images/virtualization-artifact/pkg/controller/vmd_importer.go index 8045a446d..fd48b3d3e 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_importer.go +++ b/images/virtualization-artifact/pkg/controller/vmd_importer.go @@ -21,7 +21,7 @@ func (r *VMDReconciler) startImporterPod(ctx context.Context, state *VMDReconcil return nil } - opts.Log.V(1).Info("Creating importer POD for VMD", "vmd.Name", vmd.Name) + opts.Log.V(1).Info("Creating importer POD for VD", "vd.Name", vmd.Name) importerSettings, err := r.createImporterSettings(state) if err != nil { @@ -66,21 +66,22 @@ func (r *VMDReconciler) createImporterSettings(state *VMDReconcilerState) (*impo return nil, fmt.Errorf("dataSource '%s' specified without related 'containerImage' section", ds.Type) } importer.ApplyRegistrySourceSettings(settings, ds.ContainerImage, state.Supplements) - case virtv2alpha1.DataSourceTypeClusterVirtualMachineImage: - cvmiRef := ds.ClusterVirtualMachineImage - if cvmiRef == nil { - return nil, fmt.Errorf("dataSource '%s' specified without related 'clusterVirtualMachineImage' section", ds.Type) + case virtv2alpha1.DataSourceTypeObjectRef: + if ds.ObjectRef == nil { + return nil, fmt.Errorf("dataSource '%s' specified without related 'objectRef' section", ds.Type) } - dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(cvmiRef.Name) - importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) - case virtv2alpha1.DataSourceTypeVirtualMachineImage: - vmiRef := ds.VirtualMachineImage - if vmiRef == nil { - return nil, fmt.Errorf("dataSource '%s' specified without related 'virtualMachineImage' section", ds.Type) + + switch ds.ObjectRef.Kind { + case virtv2alpha1.VirtualDiskObjectRefKindVirtualImage: + // Note: use namespace from the current VMD resource. + dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(ds.ObjectRef.Name, vmd.Namespace) + importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) + case virtv2alpha1.VirtualDiskObjectRefKindClusterVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ObjectRef.Name) + importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) + default: + return nil, fmt.Errorf("unknown objectRef kind: %s", ds.ObjectRef.Kind) } - // Note: use namespace from the current VMD resource. - dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(vmiRef.Name, vmd.Namespace) - importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) default: return nil, fmt.Errorf("unknown dataSource: %s", ds.Type) } diff --git a/images/virtualization-artifact/pkg/controller/vmd_reconciler.go b/images/virtualization-artifact/pkg/controller/vmd_reconciler.go index aeab85669..53711d717 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/vmd_reconciler.go @@ -37,7 +37,7 @@ import ( ) type VMDReconciler struct { - *vmattachee.AttacheeReconciler[*virtv2.VirtualMachineDisk, virtv2.VirtualMachineDiskStatus] + *vmattachee.AttacheeReconciler[*virtv2.VirtualDisk, virtv2.VirtualDiskStatus] importerImage string uploaderImage string @@ -54,21 +54,21 @@ func NewVMDReconciler(importerImage, uploaderImage, verbose, pullPolicy string, pullPolicy: pullPolicy, dvcrSettings: dvcrSettings, AttacheeReconciler: vmattachee.NewAttacheeReconciler[ - *virtv2.VirtualMachineDisk, - virtv2.VirtualMachineDiskStatus, + *virtv2.VirtualDisk, + virtv2.VirtualDiskStatus, ](), } } func (r *VMDReconciler) SetupController(ctx context.Context, mgr manager.Manager, ctr controller.Controller) error { - if err := ctr.Watch(source.Kind(mgr.GetCache(), &virtv2.VirtualMachineDisk{}), &handler.EnqueueRequestForObject{}, + if err := ctr.Watch(source.Kind(mgr.GetCache(), &virtv2.VirtualDisk{}), &handler.EnqueueRequestForObject{}, predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { return true }, DeleteFunc: func(e event.DeleteEvent) bool { return true }, UpdateFunc: func(e event.UpdateEvent) bool { return true }, }, ); err != nil { - return fmt.Errorf("error setting watch on VMD: %w", err) + return fmt.Errorf("error setting watch on virtual disk: %w", err) } if err := ctr.Watch( @@ -76,7 +76,7 @@ func (r *VMDReconciler) SetupController(ctx context.Context, mgr manager.Manager handler.EnqueueRequestForOwner( mgr.GetScheme(), mgr.GetRESTMapper(), - &virtv2.VirtualMachineDisk{}, + &virtv2.VirtualDisk{}, handler.OnlyControllerOwner(), ), ); err != nil { @@ -88,7 +88,7 @@ func (r *VMDReconciler) SetupController(ctx context.Context, mgr manager.Manager handler.EnqueueRequestForOwner( mgr.GetScheme(), mgr.GetRESTMapper(), - &virtv2.VirtualMachineDisk{}, + &virtv2.VirtualDisk{}, handler.OnlyControllerOwner(), ), predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { return false }, @@ -104,9 +104,9 @@ func (r *VMDReconciler) SetupController(ctx context.Context, mgr manager.Manager // Sync starts an importer Pod and creates a DataVolume to import image into PVC. func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - log := opts.Log.WithValues("vmd.name", state.VMD.Current().GetName()) + log := opts.Log.WithValues("vd.name", state.VMD.Current().GetName()) - log.V(2).Info("Sync VMD") + log.V(2).Info("Sync VD") if r.AttacheeReconciler.Sync(ctx, state.AttacheeState, opts) { return nil @@ -114,7 +114,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM switch { case state.IsDeletion(): - log.V(1).Info("Delete VMD, remove protective finalizers") + log.V(1).Info("Delete VD, remove protective finalizers") return r.cleanupOnDeletion(ctx, state, opts) case !state.IsProtected(): // Set protective finalizer atomically. @@ -125,7 +125,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM case state.IsLost(): return nil case state.IsReady(): - opts.Log.Info("VMD ready: cleanup underlying resources") + opts.Log.Info("virtual disk ready: cleanup underlying resources") // Delete underlying importer/uploader Pod, Service and DataVolume and stop the reconcile process. if cc.ShouldCleanupSubResources(state.VMD.Current()) { if err := r.cleanup(ctx, state.VMD.Changed(), state.Client, state); err != nil { @@ -163,7 +163,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil case state.IsFailed(): - opts.Log.Info("VMD failed: cleanup underlying resources") + opts.Log.Info("virtual disk failed: cleanup underlying resources") // Delete underlying importer/uploader Pod, Service and DataVolume and stop the reconcile process. if cc.ShouldCleanupSubResources(state.VMD.Current()) { if err := r.cleanup(ctx, state.VMD.Changed(), state.Client, state); err != nil { @@ -178,7 +178,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM switch { case state.CanStartPod(): // Create Pod using name and namespace from annotation. - log.V(1).Info("Start new Pod for VMD") + log.V(1).Info("Start new Pod for virtual disk") // Create importer/uploader pod, make sure the VMD owns it. if err := r.startPod(ctx, state, opts); err != nil { return err @@ -188,7 +188,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil case state.Pod != nil: // Import is in progress, force a re-reconcile in 2 seconds to update status. - log.V(2).Info("Requeue: wait until Pod is completed", "vmd.name", state.VMD.Current().Name) + log.V(2).Info("Requeue: wait until Pod is completed", "vd.name", state.VMD.Current().Name) if err := r.ensurePodFinalizers(ctx, state, opts); err != nil { return err } @@ -216,7 +216,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM } } - log.V(1).Info("Create DataVolume for VMD") + log.V(1).Info("Create DataVolume for VD") err := r.createDataVolume(ctx, state.VMD.Current(), state, opts) if err != nil { @@ -235,7 +235,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil case state.DV != nil: // Import is in progress, force a re-reconcile in 2 seconds to update status. - log.V(2).Info("Requeue: wait until DataVolume is completed", "vmd.name", state.VMD.Current().Name) + log.V(2).Info("Requeue: wait until DataVolume is completed", "vd.name", state.VMD.Current().Name) if state.IsDataVolumeComplete() { err := r.setPVCOwnerReference(ctx, state, opts.Client) @@ -255,7 +255,7 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM } // Report unexpected state. - details := fmt.Sprintf("vmd.Status.Phase='%s'", state.VMD.Current().Status.Phase) + details := fmt.Sprintf("vd.Status.Phase='%s'", state.VMD.Current().Status.Phase) if state.Pod != nil { details += fmt.Sprintf(" pod.Name='%s' pod.Status.Phase='%s'", state.Pod.Name, state.Pod.Status.Phase) } @@ -265,15 +265,15 @@ func (r *VMDReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM if state.PVC != nil { details += fmt.Sprintf(" pvc.Name='%s' pvc.Status.Phase='%s'", state.PVC.Name, state.PVC.Status.Phase) } - opts.Recorder.Event(state.VMD.Current(), corev1.EventTypeWarning, virtv2.ReasonErrUnknownState, fmt.Sprintf("VMD has unexpected state, recreate it to start import again. %s", details)) + opts.Recorder.Event(state.VMD.Current(), corev1.EventTypeWarning, virtv2.ReasonErrUnknownState, fmt.Sprintf("virtual disk has unexpected state, recreate it to start import again. %s", details)) return nil } func (r *VMDReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - log := opts.Log.WithValues("vmd.name", state.VMD.Current().GetName()) + log := opts.Log.WithValues("vd.name", state.VMD.Current().GetName()) - log.V(2).Info("Update VMD status") + log.V(2).Info("Update VD status") // Do nothing if object is being deleted as any update will lead to en error. if state.IsDeletion() { @@ -305,7 +305,7 @@ func (r *VMDReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta state.SetReconcilerResult(&reconcile.Result{Requeue: true}) case state.IsReady(): if state.PVC == nil { - log.V(1).Info("PVC not found for ready vmd") + log.V(1).Info("PVC not found for ready vd") vmdStatus.Phase = virtv2.DiskPVCLost break } @@ -414,7 +414,7 @@ func (r *VMDReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta } case state.ShouldTrackDataVolume() && state.IsDataVolumeComplete(): if state.PVC == nil { - log.V(1).Info("PVC not found for completed vmd") + log.V(1).Info("PVC not found for completed vd") vmdStatus.Phase = virtv2.DiskPVCLost break } @@ -437,7 +437,7 @@ func (r *VMDReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta vmdStatus.DownloadSpeed.CurrentBytes = "" // PVC name is the same as the DataVolume name. - vmdStatus.Target.PersistentVolumeClaimName = state.PVC.Name + vmdStatus.Target.PersistentVolumeClaim = state.PVC.Name // Copy capacity from PVC if IsDataVolumeInProgress was very quick. vmdStatus.Capacity = util.GetPointer(state.PVC.Status.Capacity[corev1.ResourceStorage]).String() @@ -607,7 +607,7 @@ func (r *VMDReconciler) startPod( return nil } -func (r *VMDReconciler) cleanup(ctx context.Context, vmd *virtv2.VirtualMachineDisk, client client.Client, state *VMDReconcilerState) error { +func (r *VMDReconciler) cleanup(ctx context.Context, vmd *virtv2.VirtualDisk, client client.Client, state *VMDReconcilerState) error { if state.DV != nil { err := supplements.CleanupForDataVolume(ctx, client, state.Supplements, r.dvcrSettings) if err != nil { @@ -679,8 +679,8 @@ func (r *VMDReconciler) cleanupOnDeletion(ctx context.Context, state *VMDReconci } func (r *VMDReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type == virtv2.DiskDevice && bda.VirtualMachineDisk != nil { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.DiskDevice { return true } } @@ -691,13 +691,13 @@ func (r *VMDReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { func (r *VMDReconciler) EnqueueFromAttachedVM(vm *virtv2.VirtualMachine) []reconcile.Request { var requests []reconcile.Request - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type != virtv2.DiskDevice || bda.VirtualMachineDisk == nil { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind != virtv2.DiskDevice { continue } requests = append(requests, reconcile.Request{NamespacedName: types.NamespacedName{ - Name: bda.VirtualMachineDisk.Name, + Name: bda.Name, Namespace: vm.Namespace, }}) } diff --git a/images/virtualization-artifact/pkg/controller/vmd_reconciler_state.go b/images/virtualization-artifact/pkg/controller/vmd_reconciler_state.go index 464ea1f3d..e2953502d 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/vmd_reconciler_state.go @@ -25,13 +25,13 @@ import ( ) type VMDReconcilerState struct { - *vmattachee.AttacheeState[*virtv2.VirtualMachineDisk, virtv2.VirtualMachineDiskStatus] + *vmattachee.AttacheeState[*virtv2.VirtualDisk, virtv2.VirtualDiskStatus] Client client.Client Supplements *supplements.Generator Result *reconcile.Result - VMD *helper.Resource[*virtv2.VirtualMachineDisk, virtv2.VirtualMachineDiskStatus] + VMD *helper.Resource[*virtv2.VirtualDisk, virtv2.VirtualDiskStatus] DV *cdiv1.DataVolume PVC *corev1.PersistentVolumeClaim PV *corev1.PersistentVolume @@ -46,8 +46,8 @@ func NewVMDReconcilerState(name types.NamespacedName, log logr.Logger, client cl Client: client, VMD: helper.NewResource( name, log, client, cache, - func() *virtv2.VirtualMachineDisk { return &virtv2.VirtualMachineDisk{} }, - func(obj *virtv2.VirtualMachineDisk) virtv2.VirtualMachineDiskStatus { return obj.Status }, + func() *virtv2.VirtualDisk { return &virtv2.VirtualDisk{} }, + func(obj *virtv2.VirtualDisk) virtv2.VirtualDiskStatus { return obj.Status }, ), } @@ -62,7 +62,7 @@ func NewVMDReconcilerState(name types.NamespacedName, log logr.Logger, client cl func (state *VMDReconcilerState) ApplySync(ctx context.Context, _ logr.Logger) error { if err := state.VMD.UpdateMeta(ctx); err != nil { - return fmt.Errorf("unable to update VMD %q meta: %w", state.VMD.Name(), err) + return fmt.Errorf("unable to update virtual disk %q meta: %w", state.VMD.Name(), err) } return nil } @@ -86,7 +86,7 @@ func (state *VMDReconcilerState) Reload(ctx context.Context, req reconcile.Reque } if state.VMD.IsEmpty() { - log.Info("Reconcile observe an absent VMD: it may be deleted", "vmd.name", req.Name, "vmd.namespace", req.Namespace) + log.Info("Reconcile observe an absent VD: it may be deleted", "vd.name", req.Name, "vd.namespace", req.Namespace) return nil } @@ -254,8 +254,8 @@ func (state *VMDReconcilerState) IsAttachedToVM(vm virtv2.VirtualMachine) bool { return false } - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type == virtv2.DiskDevice && bda.VirtualMachineDisk != nil && bda.VirtualMachineDisk.Name == state.VMD.Name().Name { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.DiskDevice && bda.Name == state.VMD.Name().Name { return true } } diff --git a/images/virtualization-artifact/pkg/controller/vmd_reconciler_test.go b/images/virtualization-artifact/pkg/controller/vmd_reconciler_test.go index e2d4be210..a216f4f69 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_reconciler_test.go +++ b/images/virtualization-artifact/pkg/controller/vmd_reconciler_test.go @@ -23,23 +23,23 @@ package controller_test // var dvName string // // { -// vmd := &virtv2.VirtualMachineDisk{ +// vmd := &virtv2.VirtualDisk{ // ObjectMeta: metav1.ObjectMeta{ // Name: "test-vmd", // Namespace: "test-ns", // Labels: nil, // Annotations: nil, // }, -// Spec: virtv2.VirtualMachineDiskSpec{ -// DataSource: &virtv2.VMDDataSource{ +// Spec: virtv2.VirtualDiskSpec{ +// DataSource: &virtv2.VirtualDiskDataSource{ // Type: virtv2.DataSourceTypeHTTP, // HTTP: &virtv2.DataSourceHTTP{ // URL: "http://mydomain.org/image.img", // }, // }, -// PersistentVolumeClaim: virtv2.VMDPersistentVolumeClaim{ +// PersistentVolumeClaim: virtv2.VirtualDiskPersistentVolumeClaim{ // Size: "10Gi", -// StorageClassName: "local-path", +// StorageClass: "local-path", // }, // }, // } @@ -47,8 +47,8 @@ package controller_test // reconciler = controller.NewVMDReconciler(controller.TestReconcilerOptions{ // KnownObjects: []client.Object{ // &virtv2.VirtualMachine{}, -// &virtv2.VirtualMachineDisk{}, -// &virtv2.ClusterVirtualMachineImage{}, +// &virtv2.VirtualDisk{}, +// &virtv2.ClusterVirtualImage{}, // &cdiv1.DataVolume{}, // }, // RuntimeObjects: []runtime.Object{vmd}, @@ -60,13 +60,13 @@ package controller_test // err := reconcileExecutor.Execute(ctx, reconciler) // Expect(err).NotTo(HaveOccurred()) // -// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualMachineDisk{}) +// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualDisk{}) // Expect(err).NotTo(HaveOccurred()) // Expect(vmd).NotTo(BeNil()) // Expect(vmd.Status.Phase).To(Equal(virtv2.DiskPending)) // Expect(vmd.Status.Progress).To(Equal("N/A")) // Expect(vmd.Status.Capacity).To(Equal("")) -// Expect(vmd.Status.Target.PersistentVolumeClaimName).To(Equal("")) +// Expect(vmd.Status.Target.PersistentVolumeClaim).To(Equal("")) // // // UUID suffix // Expect(strings.HasPrefix(vmd.Annotations[controller.AnnVMDDataVolume], "virtual-machine-disk-")).To(BeTrue(), fmt.Sprintf("unexpected DataVolume name %q", vmd.Annotations[controller.AnnVMDDataVolume])) @@ -77,13 +77,13 @@ package controller_test // err := reconcileExecutor.Execute(ctx, reconciler) // Expect(err).NotTo(HaveOccurred()) // -// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualMachineDisk{}) +// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualDisk{}) // Expect(err).NotTo(HaveOccurred()) // Expect(vmd).NotTo(BeNil()) // Expect(vmd.Status.Phase).To(Equal(virtv2.DiskPending)) // Expect(vmd.Status.Progress).To(Equal("N/A")) // Expect(vmd.Status.Capacity).To(Equal("")) -// Expect(vmd.Status.Target.PersistentVolumeClaimName).To(Equal("")) +// Expect(vmd.Status.Target.PersistentVolumeClaim).To(Equal("")) // // dvName = vmd.Annotations[controller.AnnVMDDataVolume] // dv, err := helper.FetchObject(ctx, types.NamespacedName{Name: dvName, Namespace: "test-ns"}, reconciler.Client, &cdiv1.DataVolume{}) @@ -102,13 +102,13 @@ package controller_test // err = reconcileExecutor.Execute(ctx, reconciler) // Expect(err).NotTo(HaveOccurred()) // -// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualMachineDisk{}) +// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualDisk{}) // Expect(err).NotTo(HaveOccurred()) // Expect(vmd).NotTo(BeNil()) // Expect(vmd.Status.Phase).To(Equal(virtv2.DiskPending)) // Expect(vmd.Status.Progress).To(Equal("N/A")) // Expect(vmd.Status.Capacity).To(Equal("")) -// Expect(vmd.Status.Target.PersistentVolumeClaimName).To(Equal("")) +// Expect(vmd.Status.Target.PersistentVolumeClaim).To(Equal("")) // } // // { @@ -135,7 +135,7 @@ package controller_test // Annotations: nil, // }, // Spec: corev1.PersistentVolumeClaimSpec{ -// StorageClassName: util.GetPointer("local-path"), +// StorageClass: util.GetPointer("local-path"), // VolumeName: pv.Name, // }, // Status: corev1.PersistentVolumeClaimStatus{ @@ -159,13 +159,13 @@ package controller_test // err = reconcileExecutor.Execute(ctx, reconciler) // Expect(err).NotTo(HaveOccurred()) // -// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualMachineDisk{}) +// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualDisk{}) // Expect(err).NotTo(HaveOccurred()) // Expect(vmd).NotTo(BeNil()) // Expect(vmd.Status.Phase).To(Equal(virtv2.DiskProvisioning)) // Expect(vmd.Status.Progress).To(Equal("50%")) // Expect(vmd.Status.Capacity).To(Equal("15Gi")) -// Expect(vmd.Status.Target.PersistentVolumeClaimName).To(Equal("")) +// Expect(vmd.Status.Target.PersistentVolumeClaim).To(Equal("")) // } // // { @@ -180,13 +180,13 @@ package controller_test // err = reconcileExecutor.Execute(ctx, reconciler) // Expect(err).NotTo(HaveOccurred()) // -// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualMachineDisk{}) +// vmd, err := helper.FetchObject(ctx, types.NamespacedName{Name: "test-vmd", Namespace: "test-ns"}, reconciler.Client, &virtv2.VirtualDisk{}) // Expect(err).NotTo(HaveOccurred()) // Expect(vmd).NotTo(BeNil()) // Expect(vmd.Status.Phase).To(Equal(virtv2.DiskReady)) // Expect(vmd.Status.Progress).To(Equal("100%")) // Expect(vmd.Status.Capacity).To(Equal("15Gi")) -// Expect(vmd.Status.Target.PersistentVolumeClaimName).To(Equal(dvName)) +// Expect(vmd.Status.Target.PersistentVolumeClaim).To(Equal(dvName)) // } // }) // }) diff --git a/images/virtualization-artifact/pkg/controller/vmd_uploader.go b/images/virtualization-artifact/pkg/controller/vmd_uploader.go index 70d001349..1caf190e6 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_uploader.go +++ b/images/virtualization-artifact/pkg/controller/vmd_uploader.go @@ -14,7 +14,7 @@ import ( func (r *VMDReconciler) startUploaderPod(ctx context.Context, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { vmd := state.VMD.Current() - opts.Log.V(1).Info("Creating uploader POD for VMD", "vmd.Name", vmd.Name) + opts.Log.V(1).Info("Creating uploader POD for VD", "vd.Name", vmd.Name) uploaderSettings := r.createUploaderSettings(state) @@ -68,7 +68,7 @@ func (r *VMDReconciler) createUploaderPodSettings(state *VMDReconcilerState) *up } func (r *VMDReconciler) startUploaderService(ctx context.Context, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(1).Info("Creating uploader Service for VMD", "vmd.Name", state.VMD.Current().Name) + opts.Log.V(1).Info("Creating uploader Service for VD", "vd.Name", state.VMD.Current().Name) uploaderService := uploader.NewService(r.createUploaderServiceSettings(state)) @@ -92,7 +92,7 @@ func (r *VMDReconciler) createUploaderServiceSettings(state *VMDReconcilerState) } func (r *VMDReconciler) startUploaderIngress(ctx context.Context, state *VMDReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(1).Info("Creating uploader Ingress for VMD", "vmd.Name", state.VMD.Current().Name) + opts.Log.V(1).Info("Creating uploader Ingress for VD", "vd.Name", state.VMD.Current().Name) uploaderIng := uploader.NewIngress(r.createUploaderIngressSettings(state)) diff --git a/images/virtualization-artifact/pkg/controller/vmd_webhook.go b/images/virtualization-artifact/pkg/controller/vmd_webhook.go index 444d9f5ff..bd68f9218 100644 --- a/images/virtualization-artifact/pkg/controller/vmd_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vmd_webhook.go @@ -21,36 +21,36 @@ type VMDValidator struct { } func (v *VMDValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { - vmd, ok := obj.(*v1alpha2.VirtualMachineDisk) + vmd, ok := obj.(*v1alpha2.VirtualDisk) if !ok { - return nil, fmt.Errorf("expected a new VirtualMachineDisk but got a %T", obj) + return nil, fmt.Errorf("expected a new VirtualDisk but got a %T", obj) } - v.log.Info("Validating VMD", "spec.pvc.size", vmd.Spec.PersistentVolumeClaim.Size) + v.log.Info("Validating virtual disk", "spec.pvc.size", vmd.Spec.PersistentVolumeClaim.Size) if vmd.Spec.PersistentVolumeClaim.Size != nil && vmd.Spec.PersistentVolumeClaim.Size.IsZero() { return nil, fmt.Errorf("virtual machine disk size must be greater than 0") } if vmd.Spec.DataSource == nil && (vmd.Spec.PersistentVolumeClaim.Size == nil || vmd.Spec.PersistentVolumeClaim.Size.IsZero()) { - return nil, fmt.Errorf("if the data source is not specified, it's necessary to set spec.PersistentVolumeClaim.size to create blank VMD") + return nil, fmt.Errorf("if the data source is not specified, it's necessary to set spec.PersistentVolumeClaim.size to create blank virtual disk") } return nil, nil } func (v *VMDValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { - newVMD, ok := newObj.(*v1alpha2.VirtualMachineDisk) + newVMD, ok := newObj.(*v1alpha2.VirtualDisk) if !ok { - return nil, fmt.Errorf("expected a new VirtualMachineDisk but got a %T", newObj) + return nil, fmt.Errorf("expected a new VirtualDisk but got a %T", newObj) } - oldVMD, ok := oldObj.(*v1alpha2.VirtualMachineDisk) + oldVMD, ok := oldObj.(*v1alpha2.VirtualDisk) if !ok { - return nil, fmt.Errorf("expected an old VirtualMachineDisk but got a %T", oldObj) + return nil, fmt.Errorf("expected an old VirtualDisk but got a %T", oldObj) } - v.log.Info("Validating VMD", + v.log.Info("Validating virtual disk", "old.spec.pvc.size", oldVMD.Spec.PersistentVolumeClaim.Size, "new.spec.pvc.size", newVMD.Spec.PersistentVolumeClaim.Size, ) diff --git a/images/virtualization-artifact/pkg/controller/vmi_controller.go b/images/virtualization-artifact/pkg/controller/vmi_controller.go index 2433c492b..31c2f60d7 100644 --- a/images/virtualization-artifact/pkg/controller/vmi_controller.go +++ b/images/virtualization-artifact/pkg/controller/vmi_controller.go @@ -14,8 +14,8 @@ import ( ) const ( - vmiControllerName = "vmi-controller" - vmiShortName = "vmi" + vmiControllerName = "vi-controller" + vmiShortName = "vi" ) func NewVMIController( @@ -55,6 +55,6 @@ func NewVMIController( if err := reconciler.SetupController(ctx, mgr, c); err != nil { return nil, err } - log.Info("Initialized VirtualMachineImage controller") + log.Info("Initialized VirtualImage controller") return c, nil } diff --git a/images/virtualization-artifact/pkg/controller/vmi_datavolume.go b/images/virtualization-artifact/pkg/controller/vmi_datavolume.go index e48cb5634..191e3f8d5 100644 --- a/images/virtualization-artifact/pkg/controller/vmi_datavolume.go +++ b/images/virtualization-artifact/pkg/controller/vmi_datavolume.go @@ -19,7 +19,7 @@ import ( ) // getPVCSize retrieves PVC size from importer Pod final report after import is done. -func (r *VMIReconciler) getPVCSize(vmi *virtv2.VirtualMachineImage, state *VMIReconcilerState) (resource.Quantity, error) { +func (r *VMIReconciler) getPVCSize(vmi *virtv2.VirtualImage, state *VMIReconcilerState) (resource.Quantity, error) { var unpackedSize resource.Quantity switch { @@ -52,7 +52,7 @@ func (r *VMIReconciler) getPVCSize(vmi *virtv2.VirtualMachineImage, state *VMIRe return size, nil } -func (r *VMIReconciler) createDataVolume(ctx context.Context, vmi *virtv2.VirtualMachineImage, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { +func (r *VMIReconciler) createDataVolume(ctx context.Context, vmi *virtv2.VirtualImage, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { // Retrieve PVC size. pvcSize, err := r.getPVCSize(vmi, state) if err != nil { @@ -66,7 +66,7 @@ func (r *VMIReconciler) createDataVolume(ctx context.Context, vmi *virtv2.Virtua if err = opts.Client.Create(ctx, dv); err != nil { opts.Log.V(2).Info("Error create new DV spec", "dv.spec", dv.Spec) - return fmt.Errorf("create DataVolume/%s for VMI/%s: %w", dv.GetName(), vmi.GetName(), err) + return fmt.Errorf("create DataVolume/%s for VI/%s: %w", dv.GetName(), vmi.GetName(), err) } opts.Log.Info("Created new DV", "dv.name", dv.GetName()) opts.Log.V(2).Info("Created new DV spec", "dv.spec", dv.Spec) @@ -102,19 +102,27 @@ func (r *VMIReconciler) makeDataVolumeFromVMI(state *VMIReconcilerState, dvName // Use DV name for the Secret with DVCR auth and the ConfigMap with DVCR CA Bundle. dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(vmi.Name, vmi.Namespace) dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) - case ds.Type == virtv2.DataSourceTypeClusterVirtualMachineImage: - dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ClusterVirtualMachineImage.Name) - dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) - case ds.Type == virtv2.DataSourceTypeVirtualMachineImage: - vmiRef := ds.VirtualMachineImage - // NOTE: use namespace from current VMI. - dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(vmiRef.Name, vmi.Namespace) - dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) + case ds.Type == virtv2.DataSourceTypeObjectRef: + if ds.ObjectRef == nil { + return nil, fmt.Errorf("nil objectRef %q", vmiutil.GetDataSourceType(vmi)) + } + + switch ds.ObjectRef.Kind { + case virtv2.VirtualImageObjectRefKindVirtualImage: + // NOTE: use namespace from current VMI. + dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(ds.ObjectRef.Name, vmi.Namespace) + dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) + case virtv2.VirtualImageObjectRefKindClusterVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ObjectRef.Name) + dvBuilder.SetRegistryDataSource(dvcrSourceImageName, authSecretName, caBundleName) + default: + return nil, fmt.Errorf("unsupported object ref kind %q", ds.ObjectRef.Kind) + } default: return nil, fmt.Errorf("unsupported dataSource type %q", vmiutil.GetDataSourceType(vmi)) } - dvBuilder.SetPVC(vmi.Spec.PersistentVolumeClaim.StorageClassName, pvcSize) + dvBuilder.SetPVC(vmi.Spec.PersistentVolumeClaim.StorageClass, pvcSize) dvBuilder.SetOwnerRef(vmi, vmi.GetObjectKind().GroupVersionKind()) dvBuilder.AddFinalizer(virtv2.FinalizerDVProtection) diff --git a/images/virtualization-artifact/pkg/controller/vmi_importer.go b/images/virtualization-artifact/pkg/controller/vmi_importer.go index 4dedb0901..4b013805b 100644 --- a/images/virtualization-artifact/pkg/controller/vmi_importer.go +++ b/images/virtualization-artifact/pkg/controller/vmi_importer.go @@ -15,7 +15,7 @@ import ( func (r *VMIReconciler) startImporterPod(ctx context.Context, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { vmi := state.VMI.Current() - opts.Log.V(1).Info("Creating importer POD for VMI", "vmi.Name", vmi.Name) + opts.Log.V(1).Info("Creating importer POD for VI", "vi.Name", vmi.Name) importerSettings, err := r.createImporterSettings(state) if err != nil { @@ -61,21 +61,21 @@ func (r *VMIReconciler) createImporterSettings(state *VMIReconcilerState) (*impo return nil, fmt.Errorf("dataSource '%s' specified without related 'containerImage' section", ds.Type) } importer.ApplyRegistrySourceSettings(settings, ds.ContainerImage, state.Supplements) - case virtv2alpha1.DataSourceTypeClusterVirtualMachineImage: - cvmiRef := ds.ClusterVirtualMachineImage - if cvmiRef == nil { - return nil, fmt.Errorf("dataSource '%s' specified without related 'clusterVirtualMachineImage' section", ds.Type) + case virtv2alpha1.DataSourceTypeObjectRef: + if ds.ObjectRef == nil { + return nil, fmt.Errorf("dataSource '%s' specified without related 'objectRef' section", ds.Type) } - dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(cvmiRef.Name) - importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) - case virtv2alpha1.DataSourceTypeVirtualMachineImage: - vmiRef := ds.VirtualMachineImage - if vmiRef == nil { - return nil, fmt.Errorf("dataSource '%s' specified without related 'virtualMachineImage' section", ds.Type) + + switch ds.ObjectRef.Kind { + case virtv2alpha1.VirtualImageObjectRefKindVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(ds.ObjectRef.Name, vmi.Namespace) + importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) + case virtv2alpha1.VirtualImageObjectRefKindClusterVirtualImage: + dvcrSourceImageName := r.dvcrSettings.RegistryImageForCVMI(ds.ObjectRef.Name) + importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) + default: + return nil, fmt.Errorf("unknown objectRef kind: %s", ds.ObjectRef.Kind) } - // Note: use namespace from the current VMI resource. - dvcrSourceImageName := r.dvcrSettings.RegistryImageForVMI(vmiRef.Name, vmi.Namespace) - importer.ApplyDVCRSourceSettings(settings, dvcrSourceImageName) default: return nil, fmt.Errorf("unknown dataSource: %s", ds.Type) } diff --git a/images/virtualization-artifact/pkg/controller/vmi_reconciler.go b/images/virtualization-artifact/pkg/controller/vmi_reconciler.go index 1c4c1237f..78dd079d6 100644 --- a/images/virtualization-artifact/pkg/controller/vmi_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/vmi_reconciler.go @@ -37,7 +37,7 @@ import ( ) type VMIReconciler struct { - *vmattachee.AttacheeReconciler[*virtv2.VirtualMachineImage, virtv2.VirtualMachineImageStatus] + *vmattachee.AttacheeReconciler[*virtv2.VirtualImage, virtv2.VirtualImageStatus] importerImage string uploaderImage string @@ -54,21 +54,21 @@ func NewVMIReconciler(importerImage, uploaderImage, verbose, pullPolicy string, pullPolicy: pullPolicy, dvcrSettings: dvcrSettings, AttacheeReconciler: vmattachee.NewAttacheeReconciler[ - *virtv2.VirtualMachineImage, - virtv2.VirtualMachineImageStatus, + *virtv2.VirtualImage, + virtv2.VirtualImageStatus, ](), } } func (r *VMIReconciler) SetupController(ctx context.Context, mgr manager.Manager, ctr controller.Controller) error { - if err := ctr.Watch(source.Kind(mgr.GetCache(), &virtv2.VirtualMachineImage{}), &handler.EnqueueRequestForObject{}, + if err := ctr.Watch(source.Kind(mgr.GetCache(), &virtv2.VirtualImage{}), &handler.EnqueueRequestForObject{}, predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { return true }, DeleteFunc: func(e event.DeleteEvent) bool { return true }, UpdateFunc: func(e event.UpdateEvent) bool { return true }, }, ); err != nil { - return fmt.Errorf("error setting watch on VMI: %w", err) + return fmt.Errorf("error setting watch on VI: %w", err) } if err := ctr.Watch( @@ -76,7 +76,7 @@ func (r *VMIReconciler) SetupController(ctx context.Context, mgr manager.Manager handler.EnqueueRequestForOwner( mgr.GetScheme(), mgr.GetRESTMapper(), - &virtv2.VirtualMachineImage{}, + &virtv2.VirtualImage{}, handler.OnlyControllerOwner(), ), ); err != nil { @@ -88,7 +88,7 @@ func (r *VMIReconciler) SetupController(ctx context.Context, mgr manager.Manager handler.EnqueueRequestForOwner( mgr.GetScheme(), mgr.GetRESTMapper(), - &virtv2.VirtualMachineImage{}, + &virtv2.VirtualImage{}, handler.OnlyControllerOwner(), ), predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { return false }, @@ -106,7 +106,7 @@ func (r *VMIReconciler) SetupController(ctx context.Context, mgr manager.Manager // There are 3 modes of import: // - Start and track importer/uploader Pod only (e.g. dataSource is HTTP and storage is ContainerRegistry). // - Start importer/uploader Pod first and then create DataVolume (e.g. target size is unknown: dataSource is HTTP and storage is Kubernetes without specified size for PVC). -// - Create and track DataVolume only (e.g. dataSource is ClusterVirtualMachineImage and storage is Kubernetes). +// - Create and track DataVolume only (e.g. dataSource is ClusterVirtualImage and storage is Kubernetes). func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { if r.AttacheeReconciler.Sync(ctx, state.AttacheeState, opts) { return nil @@ -114,7 +114,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM switch { case state.IsDeletion(): - opts.Log.V(1).Info("Delete VMI, remove protective finalizers") + opts.Log.V(1).Info("Delete VI, remove protective finalizers") return r.cleanupOnDeletion(ctx, state, opts) case !state.IsProtected(): // Set protective finalizer atomically. @@ -123,7 +123,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil } case state.IsReady(): - opts.Log.Info("VMI ready: cleanup underlying resources") + opts.Log.Info("VI ready: cleanup underlying resources") // Delete underlying importer/uploader Pod, Service and DataVolume and stop the reconcile process. if cc.ShouldCleanupSubResources(state.VMI.Current()) { return r.cleanup(ctx, state.VMI.Changed(), state.Client, state, opts) @@ -132,7 +132,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM case state.IsLost(): return nil case state.IsFailed(): - opts.Log.Info("VMI failed: cleanup underlying resources") + opts.Log.Info("VI failed: cleanup underlying resources") // Delete underlying importer/uploader Pod, Service and DataVolume and stop the reconcile process. if cc.ShouldCleanupSubResources(state.VMI.Current()) { err := r.cleanup(ctx, state.VMI.Changed(), state.Client, state, opts) @@ -151,7 +151,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil case state.CanStartPod(): // Create Pod using name and namespace from annotation. - opts.Log.V(1).Info("Start new Pod for VMI") + opts.Log.V(1).Info("Start new Pod for VI") if err := r.verifyDataSource(state); err != nil { return err } @@ -165,7 +165,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil case state.Pod != nil: // Import is in progress, force a re-reconcile in 2 seconds to update status. - opts.Log.V(2).Info("Requeue: wait until Pod is completed", "vmi.name", state.VMI.Current().Name) + opts.Log.V(2).Info("Requeue: wait until Pod is completed", "vi.name", state.VMI.Current().Name) if err := r.ensurePodFinalizers(ctx, state, opts); err != nil { return err } @@ -184,7 +184,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM state.SetReconcilerResult(&reconcile.Result{RequeueAfter: 2 * time.Second}) return nil case state.CanCreateDataVolume(): - opts.Log.V(1).Info("Create DataVolume for VMI") + opts.Log.V(1).Info("Create DataVolume for VI") if err := r.createDataVolume(ctx, state.VMI.Current(), state, opts); err != nil { return err @@ -194,7 +194,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM return nil case state.DV != nil: // Import is in progress, force a re-reconcile in 2 seconds to update status. - opts.Log.V(2).Info("Requeue: wait until DataVolume is completed", "vmi.name", state.VMI.Current().Name) + opts.Log.V(2).Info("Requeue: wait until DataVolume is completed", "vi.name", state.VMI.Current().Name) if state.IsDataVolumeComplete() { err := r.setPVCOwnerReference(ctx, state, opts.Client) @@ -214,7 +214,7 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM } // Report unexpected state. - details := fmt.Sprintf("vmi.Status.Phase='%s'", state.VMI.Current().Status.Phase) + details := fmt.Sprintf("vi.Status.Phase='%s'", state.VMI.Current().Status.Phase) if state.Pod != nil { details += fmt.Sprintf(" pod.Name='%s' pod.Status.Phase='%s'", state.Pod.Name, state.Pod.Status.Phase) } @@ -224,13 +224,13 @@ func (r *VMIReconciler) Sync(ctx context.Context, _ reconcile.Request, state *VM if state.PVC != nil { details += fmt.Sprintf(" pvc.Name='%s' pvc.Status.Phase='%s'", state.PVC.Name, state.PVC.Status.Phase) } - opts.Recorder.Event(state.VMI.Current(), corev1.EventTypeWarning, virtv2.ReasonErrUnknownState, fmt.Sprintf("VMI has unexpected state, recreate it to start import again. %s", details)) + opts.Recorder.Event(state.VMI.Current(), corev1.EventTypeWarning, virtv2.ReasonErrUnknownState, fmt.Sprintf("VI has unexpected state, recreate it to start import again. %s", details)) return nil } func (r *VMIReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(2).Info("Update VMI status", "vmi.name", state.VMI.Current().GetName()) + opts.Log.V(2).Info("Update VI status", "vi.name", state.VMI.Current().GetName()) // Do nothing if object is being deleted as any update will lead to en error. if state.IsDeletion() { @@ -265,11 +265,11 @@ func (r *VMIReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta break case state.IsReady(): if state.ShouldTrackDataVolume() && state.PVC == nil { - opts.Log.Info("PVC not found for ready vmi with kubernetes storage") + opts.Log.Info("PVC not found for ready vi with kubernetes storage") vmiStatus.Phase = virtv2.ImagePVCLost } case state.ShouldTrackPod() && state.IsPodInProgress(): - opts.Log.V(2).Info("Fetch progress from Pod", "vmi.name", state.VMI.Current().GetName()) + opts.Log.V(2).Info("Fetch progress from Pod", "vi.name", state.VMI.Current().GetName()) vmiStatus.Phase = virtv2.ImageProvisioning if state.VMI.Current().Spec.DataSource.Type == virtv2.DataSourceTypeUpload && @@ -291,7 +291,7 @@ func (r *VMIReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta return err } if progress != nil { - opts.Log.V(2).Info("Got progress", "vmi.name", state.VMI.Current().Name, "progress", progress.Progress(), "speed", progress.AvgSpeed(), "progress.raw", progress.ProgressRaw(), "speed.raw", progress.AvgSpeedRaw()) + opts.Log.V(2).Info("Got progress", "vi.name", state.VMI.Current().Name, "progress", progress.Progress(), "speed", progress.AvgSpeed(), "progress.raw", progress.ProgressRaw(), "speed.raw", progress.AvgSpeedRaw()) // map 0-100% to 0-50%. progressPct := progress.Progress() if state.ShouldTrackDataVolume() { @@ -403,7 +403,7 @@ func (r *VMIReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta } case state.ShouldTrackDataVolume() && state.IsDataVolumeComplete(): if state.PVC == nil { - opts.Log.Info("PVC not found for completed vmi") + opts.Log.Info("PVC not found for completed vi") vmiStatus.Phase = virtv2.ImagePVCLost break } @@ -424,7 +424,7 @@ func (r *VMIReconciler) UpdateStatus(_ context.Context, _ reconcile.Request, sta vmiStatus.DownloadSpeed.CurrentBytes = "" // PVC name equals to the DataVolume name. dv := state.Supplements.DataVolume() - vmiStatus.Target.PersistentVolumeClaimName = dv.Name + vmiStatus.Target.PersistentVolumeClaim = dv.Name // Copy capacity from PVC if IsDataVolumeInProgress was very quick. vmiStatus.Capacity = util.GetPointer(state.PVC.Status.Capacity[corev1.ResourceStorage]).String() @@ -563,7 +563,7 @@ func (r *VMIReconciler) removeFinalizerChildResources(ctx context.Context, state func (r *VMIReconciler) verifyDataSource(state *VMIReconcilerState) error { switch state.VMI.Current().Spec.DataSource.Type { - case virtv2.DataSourceTypeClusterVirtualMachineImage, virtv2.DataSourceTypeVirtualMachineImage: + case virtv2.DataSourceTypeObjectRef: return state.DVCRDataSource.Validate() default: return nil @@ -594,7 +594,7 @@ func (r *VMIReconciler) startPod(ctx context.Context, state *VMIReconcilerState, func (r *VMIReconciler) cleanup( ctx context.Context, - vmi *virtv2.VirtualMachineImage, + vmi *virtv2.VirtualImage, client client.Client, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions, @@ -668,8 +668,8 @@ func (r *VMIReconciler) cleanupOnDeletion(ctx context.Context, state *VMIReconci } func (r *VMIReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type == virtv2.ImageDevice && bda.VirtualMachineImage != nil { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.ImageDevice { return true } } @@ -680,13 +680,13 @@ func (r *VMIReconciler) FilterAttachedVM(vm *virtv2.VirtualMachine) bool { func (r *VMIReconciler) EnqueueFromAttachedVM(vm *virtv2.VirtualMachine) []reconcile.Request { var requests []reconcile.Request - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type != virtv2.ImageDevice || bda.VirtualMachineImage == nil { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind != virtv2.ImageDevice { continue } requests = append(requests, reconcile.Request{NamespacedName: types.NamespacedName{ - Name: bda.VirtualMachineImage.Name, + Name: bda.Name, Namespace: vm.Namespace, }}) } diff --git a/images/virtualization-artifact/pkg/controller/vmi_reconciler_state.go b/images/virtualization-artifact/pkg/controller/vmi_reconciler_state.go index d24424de9..5a2a7aa27 100644 --- a/images/virtualization-artifact/pkg/controller/vmi_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/vmi_reconciler_state.go @@ -25,13 +25,13 @@ import ( ) type VMIReconcilerState struct { - *vmattachee.AttacheeState[*virtv2.VirtualMachineImage, virtv2.VirtualMachineImageStatus] + *vmattachee.AttacheeState[*virtv2.VirtualImage, virtv2.VirtualImageStatus] Client client.Client Supplements *supplements.Generator Result *reconcile.Result - VMI *helper.Resource[*virtv2.VirtualMachineImage, virtv2.VirtualMachineImageStatus] + VMI *helper.Resource[*virtv2.VirtualImage, virtv2.VirtualImageStatus] DV *cdiv1.DataVolume PVC *corev1.PersistentVolumeClaim PV *corev1.PersistentVolume @@ -46,8 +46,8 @@ func NewVMIReconcilerState(name types.NamespacedName, log logr.Logger, client cl Client: client, VMI: helper.NewResource( name, log, client, cache, - func() *virtv2.VirtualMachineImage { return &virtv2.VirtualMachineImage{} }, - func(obj *virtv2.VirtualMachineImage) virtv2.VirtualMachineImageStatus { return obj.Status }, + func() *virtv2.VirtualImage { return &virtv2.VirtualImage{} }, + func(obj *virtv2.VirtualImage) virtv2.VirtualImageStatus { return obj.Status }, ), } @@ -61,7 +61,7 @@ func NewVMIReconcilerState(name types.NamespacedName, log logr.Logger, client cl func (state *VMIReconcilerState) ApplySync(ctx context.Context, _ logr.Logger) error { if err := state.VMI.UpdateMeta(ctx); err != nil { - return fmt.Errorf("unable to update VMI %q meta: %w", state.VMI.Name(), err) + return fmt.Errorf("unable to update VI %q meta: %w", state.VMI.Name(), err) } return nil } @@ -88,7 +88,7 @@ func (state *VMIReconcilerState) Reload(ctx context.Context, req reconcile.Reque return fmt.Errorf("unable to get %q: %w", req.NamespacedName, err) } if state.VMI.IsEmpty() { - log.Info("Reconcile observe an absent VMI: it may be deleted", "vmi.name", req.Name, "vmi.namespace", req.Namespace) + log.Info("Reconcile observe an absent VI: it may be deleted", "vi.name", req.Name, "vi.namespace", req.Namespace) return nil } @@ -268,8 +268,8 @@ func (state *VMIReconcilerState) IsAttachedToVM(vm virtv2.VirtualMachine) bool { return false } - for _, bda := range vm.Status.BlockDevicesAttached { - if bda.Type == virtv2.ImageDevice && bda.VirtualMachineImage != nil && bda.VirtualMachineImage.Name == state.VMI.Name().Name { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.ImageDevice && bda.Name == state.VMI.Name().Name { return true } } diff --git a/images/virtualization-artifact/pkg/controller/vmi_uploader.go b/images/virtualization-artifact/pkg/controller/vmi_uploader.go index d5f1eb96f..c1d91bd97 100644 --- a/images/virtualization-artifact/pkg/controller/vmi_uploader.go +++ b/images/virtualization-artifact/pkg/controller/vmi_uploader.go @@ -14,7 +14,7 @@ import ( func (r *VMIReconciler) startUploaderPod(ctx context.Context, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { vmi := state.VMI.Current() - opts.Log.V(1).Info("Creating uploader POD for VMI", "vmi.Name", vmi.Name) + opts.Log.V(1).Info("Creating uploader POD for VI", "vi.Name", vmi.Name) uploaderSettings := r.createUploaderSettings(state) @@ -68,7 +68,7 @@ func (r *VMIReconciler) createUploaderPodSettings(state *VMIReconcilerState) *up } func (r *VMIReconciler) startUploaderService(ctx context.Context, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(1).Info("Creating uploader Service for VMI", "vmi.Name", state.VMI.Current().Name) + opts.Log.V(1).Info("Creating uploader Service for VI", "vi.Name", state.VMI.Current().Name) uploaderService := uploader.NewService(r.createUploaderServiceSettings(state)) @@ -92,7 +92,7 @@ func (r *VMIReconciler) createUploaderServiceSettings(state *VMIReconcilerState) } func (r *VMIReconciler) startUploaderIngress(ctx context.Context, state *VMIReconcilerState, opts two_phase_reconciler.ReconcilerOptions) error { - opts.Log.V(1).Info("Creating uploader Ingress for VMI", "vmi.Name", state.VMI.Current().Name) + opts.Log.V(1).Info("Creating uploader Ingress for VI", "vi.Name", state.VMI.Current().Name) uploaderIng := uploader.NewIngress(r.createUploaderIngressSettings(state)) diff --git a/images/virtualization-artifact/pkg/controller/vmop/vmop_reconciler_state.go b/images/virtualization-artifact/pkg/controller/vmop/vmop_reconciler_state.go index fb3d7f305..606f4ebe5 100644 --- a/images/virtualization-artifact/pkg/controller/vmop/vmop_reconciler_state.go +++ b/images/virtualization-artifact/pkg/controller/vmop/vmop_reconciler_state.go @@ -62,7 +62,7 @@ func (state *ReconcilerState) Reload(ctx context.Context, req reconcile.Request, return nil } - vmName := state.VMOP.Current().Spec.VirtualMachineName + vmName := state.VMOP.Current().Spec.VirtualMachine vm, err := helper.FetchObject(ctx, types.NamespacedName{Name: vmName, Namespace: req.Namespace}, client, @@ -140,10 +140,10 @@ func (state *ReconcilerState) OtherVMOPInProgress(ctx context.Context) (bool, er if err != nil { return false, err } - vmName := state.VMOP.Current().Spec.VirtualMachineName + vmName := state.VMOP.Current().Spec.VirtualMachine for _, vmop := range vmops.Items { - if vmop.GetName() == state.VMOP.Current().GetName() || vmop.Spec.VirtualMachineName != vmName { + if vmop.GetName() == state.VMOP.Current().GetName() || vmop.Spec.VirtualMachine != vmName { continue } if vmop.Status.Phase == virtv2.VMOPPhaseInProgress { @@ -171,7 +171,7 @@ func (state *ReconcilerState) GetInProgress() bool { func (state *ReconcilerState) GetKVVM(ctx context.Context) (*virtv1.VirtualMachine, error) { if state.VmIsEmpty() { - return nil, fmt.Errorf("VM %s not found", state.VMOP.Current().Spec.VirtualMachineName) + return nil, fmt.Errorf("VM %s not found", state.VMOP.Current().Spec.VirtualMachine) } kvvm := &virtv1.VirtualMachine{} key := types.NamespacedName{Name: state.VM.GetName(), Namespace: state.VM.GetNamespace()} @@ -181,7 +181,7 @@ func (state *ReconcilerState) GetKVVM(ctx context.Context) (*virtv1.VirtualMachi func (state *ReconcilerState) GetKVVMI(ctx context.Context) (*virtv1.VirtualMachineInstance, error) { if state.VmIsEmpty() { - return nil, fmt.Errorf("VM %s not found", state.VMOP.Current().Spec.VirtualMachineName) + return nil, fmt.Errorf("VM %s not found", state.VMOP.Current().Spec.VirtualMachine) } kvvmi := &virtv1.VirtualMachineInstance{} key := types.NamespacedName{Name: state.VM.GetName(), Namespace: state.VM.GetNamespace()} diff --git a/images/virtualization-artifact/pkg/dvcr/dvcr.go b/images/virtualization-artifact/pkg/dvcr/dvcr.go index 0827e4d25..4ed0ccaa2 100644 --- a/images/virtualization-artifact/pkg/dvcr/dvcr.go +++ b/images/virtualization-artifact/pkg/dvcr/dvcr.go @@ -30,9 +30,9 @@ type UploaderIngressSettings struct { } const ( - CVMIImageTmpl = "cvmi/%s" - VMIImageTmpl = "vmi/%s/%s" - VMDImageTmpl = "vmd/%s/%s" + CVMIImageTmpl = "cvi/%s" + VMIImageTmpl = "vi/%s/%s" + VMDImageTmpl = "vd/%s/%s" ) // RegistryImageForCVMI returns image name for CVMI. diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/virtualdisk/collector.go b/images/virtualization-artifact/pkg/monitoring/metrics/virtualdisk/collector.go index 98a67d7c4..312d013ab 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/virtualdisk/collector.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/virtualdisk/collector.go @@ -30,7 +30,7 @@ func SetupCollector(lister Lister, registerer prometheus.Registerer) *Collector } type Lister interface { - List() ([]virtv2.VirtualMachineDisk, error) + List() ([]virtv2.VirtualDisk, error) } type Collector struct { @@ -64,13 +64,13 @@ type scraper struct { ch chan<- prometheus.Metric } -func (s *scraper) Report(disks []virtv2.VirtualMachineDisk) { +func (s *scraper) Report(disks []virtv2.VirtualDisk) { for _, d := range disks { s.updateDiskStatusPhaseMetrics(d) } } -func (s *scraper) updateDiskStatusPhaseMetrics(disk virtv2.VirtualMachineDisk) { +func (s *scraper) updateDiskStatusPhaseMetrics(disk virtv2.VirtualDisk) { phase := disk.Status.Phase if phase == "" { phase = virtv2.DiskPending diff --git a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go index 446df6872..043af47aa 100644 --- a/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go +++ b/images/virtualization-artifact/pkg/monitoring/metrics/virtualmachine/collector.go @@ -96,7 +96,7 @@ func (s *scraper) updateVMStatusPhaseMetrics(vm virtv2.VirtualMachine) { desc, prometheus.GaugeValue, util.BoolFloat64(p.value), - vm.GetName(), vm.GetNamespace(), string(vm.GetUID()), vm.Status.NodeName, p.name, + vm.GetName(), vm.GetNamespace(), string(vm.GetUID()), vm.Status.Node, p.name, ) if err != nil { klog.Warningf("Error creating the new const metric for %s: %s", desc, err) diff --git a/images/virtualization-artifact/pkg/tls/util/util.go b/images/virtualization-artifact/pkg/tls/util/util.go index 107206103..a6e27dd69 100644 --- a/images/virtualization-artifact/pkg/tls/util/util.go +++ b/images/virtualization-artifact/pkg/tls/util/util.go @@ -9,7 +9,7 @@ import ( const CertificateBlockType string = "CERTIFICATE" func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) { - certs := []*x509.Certificate{} + var certs []*x509.Certificate for len(pemCerts) > 0 { var block *pem.Block block, pemCerts = pem.Decode(pemCerts) diff --git a/images/vmi-router/netlinkmanager/manager.go b/images/vmi-router/netlinkmanager/manager.go index da183c189..b7d2186fc 100644 --- a/images/vmi-router/netlinkmanager/manager.go +++ b/images/vmi-router/netlinkmanager/manager.go @@ -186,7 +186,7 @@ func (m *Manager) isManagedIP(ip string) (bool, error) { func (m *Manager) UpdateRoute(ctx context.Context, vm *virtv1alpha2.VirtualMachine) { // TODO Add cleanup if node was lost? // TODO What about migration? Is nodeName just changed to new node or we need some workarounds when 2 Pods are running? - if vm.Status.NodeName == "" { + if vm.Status.Node == "" { // VMI has no node assigned return } @@ -222,7 +222,7 @@ func (m *Manager) UpdateRoute(ctx context.Context, vm *virtv1alpha2.VirtualMachi // Retrieve a Cilium Node by VMs node name. ciliumNode := &ciliumv2.CiliumNode{} - err = m.client.Get(ctx, types.NamespacedName{Namespace: "", Name: vm.Status.NodeName}, ciliumNode) + err = m.client.Get(ctx, types.NamespacedName{Namespace: "", Name: vm.Status.Node}, ciliumNode) if err != nil { m.log.Error(err, "failed to get cilium node for vmi") } diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl new file mode 100644 index 000000000..c73b50b85 --- /dev/null +++ b/templates/_helpers.tpl @@ -0,0 +1,74 @@ +{{- define "strategic_affinity_patch" -}} + {{- $key := index . 0 -}} + {{- $labelValue := index . 1 -}} + '{{ include "tmplAntiAffinity" (list $key $labelValue) | fromYaml | toJson }}' +{{- end }} + +{{- define "tmplAntiAffinity" -}} + {{- $key := index . 0 -}} + {{- $labelValue := index . 1 -}} +spec: + template: + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: {{ $key }} + operator: In + values: + - {{ $labelValue }} + topologyKey: kubernetes.io/hostname +{{- end -}} + +{{- define "kubeproxy_resources" -}} +cpu: 100m +memory: 150Mi +{{- end -}} + +{{- define "nowebhook_kubeproxy_patch" -}} + '{{ include "nowebhook_kubeproxy_patch_tmpl" . | fromYaml | toJson }}' +{{- end }} + +{{- define "nowebhook_kubeproxy_patch_tmpl" -}} + {{- $ctx := index . 0 -}} + {{- $containerName := index . 1 -}} + {{- $proxyImage := include "helm_lib_module_image" (list $ctx "kubeApiProxy") }} +metadata: + annotations: + kubectl.kubernetes.io/default-container: {{ $containerName }} +spec: + template: + spec: + volumes: + - name: kube-api-proxy-kubeconfig + configMap: + name: kube-api-proxy-kubeconfig + containers: + - name: proxy + image: {{ $proxyImage }} + imagePullPolicy: IfNotPresent + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 12 }} + {{- if not ( $ctx.Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "kubeproxy_resources" . | nindent 12 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + - name: {{ $containerName }} + env: + - name: KUBECONFIG + value: /kubeconfig.local/proxy.kubeconfig + volumeMounts: + - name: kube-api-proxy-kubeconfig + mountPath: /kubeconfig.local +{{- end -}} diff --git a/templates/cdi/_helpers.tpl b/templates/cdi/_helpers.tpl new file mode 100644 index 000000000..221db64ba --- /dev/null +++ b/templates/cdi/_helpers.tpl @@ -0,0 +1,58 @@ +{{- define "cdi.apiserver_kubeproxy_patch" -}} + '{{ include "cdi.apiserver_kubeproxy_patch_tmpl" . | fromYaml | toJson }}' +{{- end }} + +{{- define "cdi.apiserver_kubeproxy_patch_tmpl" -}} + {{- $proxyImage := include "helm_lib_module_image" (list . "kubeApiProxy") }} +metadata: + annotations: + kubectl.kubernetes.io/default-container: cdi-apiserver +spec: + template: + spec: + volumes: + - name: kube-api-proxy-kubeconfig + configMap: + name: kube-api-proxy-kubeconfig + containers: + - name: proxy + image: {{ $proxyImage }} + imagePullPolicy: Always + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 12 }} + {{- if not ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "kubeproxy_resources" . | nindent 12 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + ports: + - containerPort: 24192 + name: webhook-proxy + protocol: TCP + env: + - name: WEBHOOK_ADDRESS + value: "https://127.0.0.1:8443" + - name: WEBHOOK_CERT_FILE + value: "/var/run/certs/cdi-apiserver-server-cert/tls.crt" + - name: WEBHOOK_KEY_FILE + value: "/var/run/certs/cdi-apiserver-server-cert/tls.key" + volumeMounts: + - mountPath: /var/run/certs/cdi-apiserver-server-cert + name: server-cert + readOnly: true + - name: cdi-apiserver + env: + - name: KUBECONFIG + value: /kubeconfig.local/proxy.kubeconfig + volumeMounts: + - name: kube-api-proxy-kubeconfig + mountPath: /kubeconfig.local +{{- end -}} diff --git a/templates/cdi/cdi-operator/deployment.yaml b/templates/cdi/cdi-operator/deployment.yaml index 3d16ca868..791f06a5e 100644 --- a/templates/cdi/cdi-operator/deployment.yaml +++ b/templates/cdi/cdi-operator/deployment.yaml @@ -59,6 +59,8 @@ metadata: {{- include "helm_lib_module_labels" (list .) | nindent 2 }} name: cdi-operator namespace: d8-{{ .Chart.Name }} + annotations: + kubectl.kubernetes.io/default-container: cdi-operator spec: {{- include "helm_lib_deployment_strategy_and_replicas_for_ha" . | nindent 2 }} revisionHistoryLimit: 2 @@ -72,10 +74,30 @@ spec: spec: {{- include "helm_lib_pod_anti_affinity_for_ha" (list . (dict "app" "cdi-operator")) | nindent 6 }} containers: + - name: proxy + image: {{ include "helm_lib_module_image" (list . "kubeApiProxy") }} + imagePullPolicy: IfNotPresent + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 12 }} + {{- if not ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "cdi_operator_resources" . | nindent 12 }} + {{- end }} - name: cdi-operator {{- include "helm_lib_module_container_security_context_read_only_root_filesystem_capabilities_drop_all" . | nindent 8 }} env: {{- include "cdi_images" . | nindent 8 }} + - name: KUBECONFIG + value: "/kubeconfig.local/proxy.kubeconfig" - name: DEPLOY_CLUSTER_RESOURCES value: "true" - name: OPERATOR_VERSION @@ -97,8 +119,15 @@ spec: {{- if not ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} {{- include "cdi_operator_resources" . | nindent 12 }} {{- end }} + volumeMounts: + - name: kube-api-proxy-kubeconfig + mountPath: /kubeconfig.local {{- include "helm_lib_priority_class" (tuple . "cluster-low") | nindent 6 }} {{- include "helm_lib_node_selector" (tuple . "system") | nindent 6 }} {{- include "helm_lib_tolerations" (tuple . "system") | nindent 6 }} {{- include "helm_lib_module_pod_security_context_run_as_user_nobody" . | nindent 6 }} serviceAccountName: cdi-operator + volumes: + - name: kube-api-proxy-kubeconfig + configMap: + name: kube-api-proxy-kubeconfig diff --git a/templates/cdi/cdi-operator/rbac-for-us.yaml b/templates/cdi/cdi-operator/rbac-for-us.yaml index 9bcb328d0..810371ea6 100644 --- a/templates/cdi/cdi-operator/rbac-for-us.yaml +++ b/templates/cdi/cdi-operator/rbac-for-us.yaml @@ -40,7 +40,7 @@ rules: - update - delete - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io - upload.cdi.kubevirt.io resources: - '*' @@ -123,28 +123,28 @@ rules: verbs: - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - datavolumes + - dvpinternaldatavolumes verbs: - list - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - datasources + - dvpinternaldatasources verbs: - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - cdis + - dvpinternalcdis verbs: - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - cdis/finalizers + - dvpinternalcdis/finalizers verbs: - update - apiGroups: @@ -219,7 +219,7 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - '*' verbs: @@ -286,9 +286,9 @@ rules: verbs: - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - dataimportcrons + - dvpinternaldataimportcrons verbs: - get - list diff --git a/templates/cdi/cdi.yaml b/templates/cdi/cdi.yaml index 2adca57c2..065505e9e 100644 --- a/templates/cdi/cdi.yaml +++ b/templates/cdi/cdi.yaml @@ -2,9 +2,12 @@ {{- $nodeSelectorMaster := index (include "helm_lib_node_selector" (tuple . "master") | fromYaml) "nodeSelector" | default (dict) | toJson }} {{- $tolerationsSystem := index (include "helm_lib_tolerations" (tuple . "system") | fromYaml) "tolerations" | default (list) | toJson }} {{- $tolerationsAnyNode := index (include "helm_lib_tolerations" (tuple . "any-node") | fromYaml) "tolerations" | default (list) | toJson }} +{{- $proxyImage := include "helm_lib_module_image" (list . "kubeApiProxy") | toJson }} +{{- $kubeAPIProxyRewriter := true }} +{{- $webhookProxyPort := 24192 }} --- -apiVersion: x.virtualization.deckhouse.io/v1beta1 -kind: CDI +apiVersion: internal.virtualization.deckhouse.io/v1beta1 +kind: DVPInternalCDI metadata: name: cdi namespace: d8-{{ .Chart.Name }} @@ -36,16 +39,6 @@ spec: resourceName: cdi-uploadproxy patch: '[{"op":"replace","path":"/spec/replicas","value":0}]' type: json - {{- if ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} - - resourceType: Deployment - resourceName: cdi-apiserver - patch: '[{"op":"replace","path":"/spec/template/spec/containers/0/resources/requests","value":{}}]' - type: json - - resourceType: Deployment - resourceName: cdi-deployment - patch: '[{"op":"replace","path":"/spec/template/spec/containers/0/resources/requests","value":{}}]' - type: json - {{- end }} {{- if (include "helm_lib_ha_enabled" .) }} - resourceType: Deployment @@ -54,8 +47,8 @@ spec: type: json - resourceType: Deployment resourceName: cdi-apiserver - patch: '[{"op":"replace","path":"/spec/template/spec/affinity","value":{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchExpressions":[{"key":"cdi.kubevirt.io","operator":"In","values":["cdi-apiserver"]}]},"topologyKey":"kubernetes.io/hostname"}]}}}]' - type: json + patch: {{ include "strategic_affinity_patch" (list "app" "cdi-apiserver") }} + type: strategic - resourceType: Deployment resourceName: cdi-deployment @@ -63,9 +56,89 @@ spec: type: json - resourceType: Deployment resourceName: cdi-deployment - patch: '[{"op":"replace","path":"/spec/template/spec/affinity","value":{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchExpressions":[{"key":"app","operator":"In","values":["containerized-data-importer"]}]},"topologyKey":"kubernetes.io/hostname"}]}}}]' + patch: {{ include "strategic_affinity_patch" (list "app" "containerized-data-importer") }} + type: strategic + {{- end }} + + {{- if $kubeAPIProxyRewriter }} + - resourceType: Deployment + resourceName: cdi-apiserver + patch: {{ include "cdi.apiserver_kubeproxy_patch" . }} + type: strategic + + - resourceType: Deployment + resourceName: cdi-deployment + patch: {{ include "nowebhook_kubeproxy_patch" (list . "cdi-controller") }} + type: strategic + + # Change service in webhook configurations to point to the rewriter proxy. + # Add port to cdi-api service. + - resourceName: cdi-api + resourceType: Service + patch: | + [{"op":"replace", "path":"/spec/ports/0/name", "value":"https"}] type: json + - resourceName: cdi-api + resourceType: Service + patch: | + {"spec":{"ports":[ + {"name": "webhook-proxy", + "port": {{ $webhookProxyPort }}, + "protocol": "TCP", + "targetPort": "webhook-proxy"} + ]}} + type: strategic + - resourceName: cdi-api-datavolume-mutate + resourceType: MutatingWebhookConfiguration + patch: | + {"webhooks":[ + { "name":"datavolume-mutate.cdi.kubevirt.io", + "clientConfig":{"service":{"port": {{ $webhookProxyPort }} }}} + ]} + type: strategic + - resourceName: cdi-api-dataimportcron-validate + resourceType: ValidatingWebhookConfiguration + patch: | + {"webhooks":[ + { "name":"dataimportcron-validate.cdi.kubevirt.io", + "clientConfig":{"service":{"port": {{ $webhookProxyPort }} }}} + ]} + type: strategic + - resourceName: cdi-api-datavolume-validate + resourceType: ValidatingWebhookConfiguration + patch: | + {"webhooks":[ + { "name":"datavolume-validate.cdi.kubevirt.io", + "clientConfig":{"service":{"port": {{ $webhookProxyPort }} }}} + ]} + type: strategic + - resourceName: cdi-api-populator-validate + resourceType: ValidatingWebhookConfiguration + patch: | + {"webhooks":[ + { "name":"populator-validate.cdi.kubevirt.io", + "clientConfig":{"service":{"port": {{ $webhookProxyPort }} }}} + ]} + type: strategic + - resourceName: cdi-api-validate + resourceType: ValidatingWebhookConfiguration + patch: | + {"webhooks":[ + { "name":"cdi-validate.cdi.kubevirt.io", + "clientConfig":{"service":{"port": {{ $webhookProxyPort }} }}} + ]} + type: strategic + - resourceName: objecttransfer-api-validate + resourceType: ValidatingWebhookConfiguration + patch: | + {"webhooks":[ + { "name":"objecttransfer-validate.cdi.kubevirt.io", + "clientConfig":{"service":{"port": {{ $webhookProxyPort }} }}} + ]} + type: strategic + {{- end }} + workload: nodeSelector: kubernetes.io/os: linux diff --git a/templates/kube-api-proxy-kubeconfig-cm.yaml b/templates/kube-api-proxy-kubeconfig-cm.yaml new file mode 100644 index 000000000..5373651ac --- /dev/null +++ b/templates/kube-api-proxy-kubeconfig-cm.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: kube-api-proxy-kubeconfig + namespace: d8-{{ .Chart.Name }} + {{- include "helm_lib_module_labels" (list .) | nindent 2 }} +data: + proxy.kubeconfig: | + apiVersion: v1 + kind: Config + clusters: + - cluster: + server: http://127.0.0.1:23915 + name: proxy.api.server + contexts: + - context: + cluster: proxy.api.server + name: proxy.api.server + current-context: proxy.api.server diff --git a/templates/kubevirt/_helpers.tpl b/templates/kubevirt/_helpers.tpl new file mode 100644 index 000000000..4ac1abff3 --- /dev/null +++ b/templates/kubevirt/_helpers.tpl @@ -0,0 +1,62 @@ + +{{- define "kubevirt.apiserver_kubeproxy_patch" -}} + '{{ include "kubevirt.apiserver_kubeproxy_patch_tmpl" . | fromYaml | toJson }}' +{{- end }} + + +{{- define "kubevirt.apiserver_kubeproxy_patch_tmpl" -}} + {{- $proxyImage := include "helm_lib_module_image" (list . "kubeApiProxy") }} +metadata: + annotations: + kubectl.kubernetes.io/default-container: virt-api +spec: + template: + spec: + volumes: + - name: kube-api-proxy-kubeconfig + configMap: + name: kube-api-proxy-kubeconfig + containers: + - name: proxy + image: {{ $proxyImage }} + imagePullPolicy: IfNotPresent + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 12 }} + {{- if not ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "cdi.kubeproxy_resources" . | nindent 12 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + ports: + - containerPort: 24192 + name: webhook-proxy + protocol: TCP + env: + - name: WEBHOOK_ADDRESS + value: https://127.0.0.1:8443 + - name: WEBHOOK_CERT_FILE + value: /etc/virt-api/certificates/tls.crt + - name: WEBHOOK_KEY_FILE + value: /etc/virt-api/certificates/tls.key + volumeMounts: + - name: kubevirt-virt-api-certs + mountPath: /etc/virt-api/certificates + readOnly: true + - name: virt-api + command: + - virt-api + - --kubeconfig=/kubeconfig.local/proxy.kubeconfig + volumeMounts: + - name: kube-api-proxy-kubeconfig + mountPath: /kubeconfig.local +{{- end -}} + + diff --git a/templates/kubevirt/kubevirt.yaml b/templates/kubevirt/kubevirt.yaml index 0f19517ca..87630ee9f 100644 --- a/templates/kubevirt/kubevirt.yaml +++ b/templates/kubevirt/kubevirt.yaml @@ -2,9 +2,12 @@ {{- $nodeSelectorMaster := index (include "helm_lib_node_selector" (tuple . "master") | fromYaml) "nodeSelector" | default (dict) | toJson }} {{- $tolerationsSystem := index (include "helm_lib_tolerations" (tuple . "system") | fromYaml) "tolerations" | default (list) | toJson }} {{- $tolerationsAnyNode := index (include "helm_lib_tolerations" (tuple . "any-node") | fromYaml) "tolerations" | default (list) | toJson }} +{{- $proxyImage := include "helm_lib_module_image" (list . "kubeApiProxy") | toJson }} +{{- $kubeAPIProxyRewriter := true }} +{{- $webhookProxyPort := 24192 }} --- -apiVersion: x.virtualization.deckhouse.io/v1 -kind: KubeVirt +apiVersion: internal.virtualization.deckhouse.io/v1 +kind: DVPInternalKubeVirt metadata: name: kubevirt namespace: d8-{{ .Chart.Name }} @@ -27,6 +30,9 @@ spec: - Sidecar - VolumeSnapshotDataSource customizeComponents: + flags: + api: {} + controller: {} patches: - resourceType: Deployment resourceName: virt-api @@ -52,30 +58,203 @@ spec: resourceName: virt-exportproxy patch: '[{"op":"replace","path":"/spec/replicas","value":0}]' type: json - {{- if ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} - - resourceType: Deployment - resourceName: virt-api - patch: '[{"op":"replace","path":"/spec/template/spec/containers/0/resources/requests","value":{}}]' - type: json - - resourceType: Deployment - resourceName: virt-controller - patch: '[{"op":"replace","path":"/spec/template/spec/containers/0/resources/requests","value":{}}]' - type: json - - resourceType: DaemonSet - resourceName: virt-handler - patch: '[{"op":"replace","path":"/spec/template/spec/containers/0/resources/requests","value":{}}]' - type: json - {{- end }} {{- if (include "helm_lib_ha_enabled" .) }} - resourceType: Deployment resourceName: virt-api - patch: '[{"op":"replace","path":"/spec/template/spec/affinity","value":{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchExpressions":[{"key":"kubevirt.io","operator":"In","values":["virt-api"]}]},"topologyKey":"kubernetes.io/hostname"}]}}}]' - type: json + patch: {{ include "strategic_affinity_patch" (list "kubevirt.io" "virt-api") }} + type: strategic - resourceType: Deployment resourceName: virt-controller - patch: '[{"op":"replace","path":"/spec/template/spec/affinity","value":{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchExpressions":[{"key":"kubevirt.io","operator":"In","values":["virt-controller"]}]},"topologyKey":"kubernetes.io/hostname"}]}}}]' + patch: {{ include "strategic_affinity_patch" (list "kubevirt.io" "virt-controller") }} + type: strategic + {{- end }} + + {{- if $kubeAPIProxyRewriter }} + - resourceName: virt-controller + resourceType: Deployment + patch: {{ include "nowebhook_kubeproxy_patch" (list . "virt-controller") }} + type: strategic + + - resourceName: virt-api + resourceType: Deployment + patch: {{ include "kubevirt.apiserver_kubeproxy_patch" . }} + type: strategic + + - resourceName: virt-handler + resourceType: DaemonSet + patch: {{ include "nowebhook_kubeproxy_patch" (list . "virt-handler") }} + type: strategic + + - resourceName: virt-exportproxy + resourceType: Deployment + patch: {{ include "nowebhook_kubeproxy_patch" (list . "exportproxy") }} + type: strategic + + # Patch services used in webhook configurations, add webhook-proxy port 24192. + - resourceName: virt-api + resourceType: Service + patch: | + [{"op":"replace", "path":"/spec/ports/0/name", "value":"https"}] type: json + - resourceName: virt-api + resourceType: Service + patch: | + {"spec":{"ports":[ + {"name": "webhook-proxy", + "port": {{ $webhookProxyPort }}, + "protocol": "TCP", + "targetPort": "webhook-proxy"} + ]}} + type: strategic + - resourceName: kubevirt-operator-webhook + resourceType: Service + patch: | + {"spec":{"ports":[ + {"name": "webhook-proxy", + "port": {{ $webhookProxyPort }}, + "protocol": "TCP", + "targetPort": "webhook-proxy"} + ]}} + type: strategic + # Change service in webhook configuration to point to the rewriter proxy. + # Patch was produced with this jq command: + # kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io virt-api-validator -o json | jq '{"webhooks": .webhooks|map({"name":.name, "clientConfig":{"service":{"port":24192}}}) }' + # virt-api-webhook-proxy service is created separately. + - resourceName: virt-api-validator + resourceType: ValidatingWebhookConfiguration + patch: | + { + "webhooks": [ + { + "name": "virt-launcher-eviction-interceptor.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineinstances-create-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineinstances-update-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachine-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachinereplicaset-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachinepool-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachinepreset-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "migration-create-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "migration-update-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachinesnapshot-validator.snapshot.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachinerestore-validator.snapshot.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineexport-validator.export.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineinstancetype-validator.instancetype.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineclusterinstancetype-validator.instancetype.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachinepreference-validator.instancetype.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineclusterpreference-validator.instancetype.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "kubevirt-crd-status-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "migration-policy-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "vm-clone-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + } + ] + } + type: strategic + # Change service in webhook configuration to point to the rewriter proxy. + # Patch was produced with this jq command: + # kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io virt-api-mutator -o json | jq '{"webhooks": .webhooks|map({"name":.name, "clientConfig":{"service":{"port":24192}}}) }' + # virt-api-webhook-proxy service is created separately. + - resourceName: virt-api-mutator + resourceType: MutatingWebhookConfiguration + patch: | + { + "webhooks": [ + { + "name": "virtualmachines-mutator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineinstances-mutator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "migrations-mutator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "virtualmachineclones-mutator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + } + ] + } + type: strategic + # Change service in webhook configuration to point to the rewriter proxy. + # Patch was produced with this jq command: + # kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io virt-operator-validator -o json | jq '{"webhooks": .webhooks|map({"name":.name, "clientConfig":{"service":{"port":24192}}}) }' + # kubevirt-operator-webhook-proxy service is created separately. + - resourceName: virt-operator-validator + resourceType: ValidatingWebhookConfiguration + patch: | + { + "webhooks": [ + { + "name": "kubevirt-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + }, + { + "name": "kubevirt-update-validator.kubevirt.io", + "clientConfig": {"service": {"port": {{ $webhookProxyPort }} }} + } + ] + } + + type: strategic {{- end }} + imagePullPolicy: IfNotPresent imagePullSecrets: - name: virtualization-module-registry diff --git a/templates/kubevirt/virt-operator/deployment.yaml b/templates/kubevirt/virt-operator/deployment.yaml index cb89c8603..36166118f 100644 --- a/templates/kubevirt/virt-operator/deployment.yaml +++ b/templates/kubevirt/virt-operator/deployment.yaml @@ -61,6 +61,8 @@ metadata: {{- include "helm_lib_module_labels" (list . (dict "app" "virt-operator")) | nindent 2 }} name: virt-operator namespace: d8-{{ .Chart.Name }} + annotations: + kubectl.kubernetes.io/default-container: virt-operator spec: {{- include "helm_lib_deployment_strategy_and_replicas_for_ha" . | nindent 2 }} revisionHistoryLimit: 2 @@ -88,9 +90,44 @@ spec: topologyKey: kubernetes.io/hostname weight: 1 containers: + - name: proxy + image: {{ include "helm_lib_module_image" (list . "kubeApiProxy") }} + imagePullPolicy: Always + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 12 }} + {{- if not ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "cdi_operator_resources" . | nindent 12 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + ports: + - containerPort: 24192 + name: webhook-proxy + protocol: TCP + env: + - name: WEBHOOK_ADDRESS + value: "https://127.0.0.1:8444" + - name: WEBHOOK_CERT_FILE + value: "/etc/virt-operator/certificates/tls.crt" + - name: WEBHOOK_KEY_FILE + value: "/etc/virt-operator/certificates/tls.key" + volumeMounts: + - mountPath: /etc/virt-operator/certificates + name: kubevirt-operator-certs + readOnly: true - name: virt-operator {{- include "helm_lib_module_container_security_context_read_only_root_filesystem_capabilities_drop_all" . | nindent 8 }} args: + - --kubeconfig + - /kubeconfig.local/proxy.kubeconfig - --port - "8443" - -v @@ -131,6 +168,8 @@ spec: readOnly: true - mountPath: /profile-data name: profile-data + - mountPath: /kubeconfig.local + name: kube-api-proxy-kubeconfig {{- include "helm_lib_priority_class" (tuple . "system-cluster-critical") | nindent 6 }} {{- include "helm_lib_node_selector" (tuple . "master") | nindent 6 }} {{- include "helm_lib_tolerations" (tuple . "any-node") | nindent 6 }} @@ -143,3 +182,6 @@ spec: secretName: kubevirt-operator-certs - emptyDir: {} name: profile-data + - name: kube-api-proxy-kubeconfig + configMap: + name: kube-api-proxy-kubeconfig diff --git a/templates/kubevirt/virt-operator/rbac-for-us.yaml b/templates/kubevirt/virt-operator/rbac-for-us.yaml index 97d02eb39..26c39807d 100644 --- a/templates/kubevirt/virt-operator/rbac-for-us.yaml +++ b/templates/kubevirt/virt-operator/rbac-for-us.yaml @@ -86,9 +86,9 @@ metadata: name: d8:virtualization:kubevirt-operator rules: - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - kubevirts + - dvpinternalkubevirts verbs: - get - list @@ -294,10 +294,10 @@ rules: - delete - patch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines - - virtualmachineinstances + - dvpinternalvirtualmachines + - dvpinternalvirtualmachineinstances verbs: - get - list @@ -311,15 +311,15 @@ rules: verbs: - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines/status + - dvpinternalvirtualmachines/status verbs: - patch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancemigrations + - dvpinternalvirtualmachineinstancemigrations verbs: - create - get @@ -327,9 +327,9 @@ rules: - watch - patch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancepresets + - dvpinternalvirtualmachineinstancepresets verbs: - watch - list @@ -357,50 +357,50 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - kubevirts + - dvpinternalkubevirts verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinesnapshots - - virtualmachinerestores - - virtualmachinesnapshotcontents + - dvpinternalvirtualmachinesnapshots + - dvpinternalvirtualmachinerestores + - dvpinternalvirtualmachinesnapshotcontents verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - datasources - - datavolumes + - dvpinternaldatasources + - dvpinternaldatavolumes verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancetypes - - virtualmachineclusterinstancetypes - - virtualmachinepreferences - - virtualmachineclusterpreferences + - dvpinternalvirtualmachineinstancetypes + - dvpinternalvirtualmachineclusterinstancetypes + - dvpinternalvirtualmachinepreferences + - dvpinternalvirtualmachineclusterpreferences verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancetypes - - virtualmachineclusterinstancetypes - - virtualmachinepreferences - - virtualmachineclusterpreferences + - dvpinternalvirtualmachineinstancetypes + - dvpinternalvirtualmachineclusterinstancetypes + - dvpinternalvirtualmachinepreferences + - dvpinternalvirtualmachineclusterpreferences verbs: - delete - create @@ -408,9 +408,9 @@ rules: - patch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - migrationpolicies + - dvpinternalmigrationpolicies verbs: - get - list @@ -550,24 +550,24 @@ rules: - delete - patch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - '*' verbs: - '*' - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - '*' verbs: - '*' - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinepools - - virtualmachinepools/finalizers - - virtualmachinepools/status - - virtualmachinepools/scale + - dvpinternalvirtualmachinepools + - dvpinternalvirtualmachinepools/finalizers + - dvpinternalvirtualmachinepools/status + - dvpinternalvirtualmachinepools/scale verbs: - watch - list @@ -577,7 +577,7 @@ rules: - patch - get - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - '*' verbs: @@ -593,7 +593,7 @@ rules: verbs: - update - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - '*' verbs: @@ -648,30 +648,30 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancetypes - - virtualmachineclusterinstancetypes - - virtualmachinepreferences - - virtualmachineclusterpreferences + - dvpinternalvirtualmachineinstancetypes + - dvpinternalvirtualmachineclusterinstancetypes + - dvpinternalvirtualmachinepreferences + - dvpinternalvirtualmachineclusterpreferences verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - migrationpolicies + - dvpinternalmigrationpolicies verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineclones - - virtualmachineclones/status - - virtualmachineclones/finalizers + - dvpinternalvirtualmachineclones + - dvpinternalvirtualmachineclones/status + - dvpinternalvirtualmachineclones/finalizers verbs: - get - list @@ -717,9 +717,9 @@ rules: - get - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstances + - dvpinternalvirtualmachineinstances verbs: - update - list @@ -757,17 +757,17 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - kubevirts + - dvpinternalkubevirts verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - migrationpolicies + - dvpinternalmigrationpolicies verbs: - get - list @@ -781,17 +781,17 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineexports + - dvpinternalvirtualmachineexports verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - kubevirts + - dvpinternalkubevirts verbs: - list - watch @@ -864,13 +864,13 @@ rules: verbs: - update - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines - - virtualmachineinstances - - virtualmachineinstancepresets - - virtualmachineinstancereplicasets - - virtualmachineinstancemigrations + - dvpinternalvirtualmachines + - dvpinternalvirtualmachineinstances + - dvpinternalvirtualmachineinstancepresets + - dvpinternalvirtualmachineinstancereplicasets + - dvpinternalvirtualmachineinstancemigrations verbs: - get - delete @@ -881,11 +881,11 @@ rules: - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinesnapshots - - virtualmachinesnapshotcontents - - virtualmachinerestores + - dvpinternalvirtualmachinesnapshots + - dvpinternalvirtualmachinesnapshotcontents + - dvpinternalvirtualmachinerestores verbs: - get - delete @@ -896,9 +896,9 @@ rules: - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineexports + - dvpinternalvirtualmachineexports verbs: - get - delete @@ -909,9 +909,9 @@ rules: - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineclones + - dvpinternalvirtualmachineclones verbs: - get - delete @@ -922,12 +922,12 @@ rules: - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancetypes - - virtualmachineclusterinstancetypes - - virtualmachinepreferences - - virtualmachineclusterpreferences + - dvpinternalvirtualmachineinstancetypes + - dvpinternalvirtualmachineclusterinstancetypes + - dvpinternalvirtualmachinepreferences + - dvpinternalvirtualmachineclusterpreferences verbs: - get - delete @@ -938,9 +938,9 @@ rules: - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinepools + - dvpinternalvirtualmachinepools verbs: - get - delete @@ -951,9 +951,9 @@ rules: - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - migrationpolicies + - dvpinternalmigrationpolicies verbs: - get - list @@ -1009,13 +1009,13 @@ rules: verbs: - update - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines - - virtualmachineinstances - - virtualmachineinstancepresets - - virtualmachineinstancereplicasets - - virtualmachineinstancemigrations + - dvpinternalvirtualmachines + - dvpinternalvirtualmachineinstances + - dvpinternalvirtualmachineinstancepresets + - dvpinternalvirtualmachineinstancereplicasets + - dvpinternalvirtualmachineinstancemigrations verbs: - get - delete @@ -1025,11 +1025,11 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinesnapshots - - virtualmachinesnapshotcontents - - virtualmachinerestores + - dvpinternalvirtualmachinesnapshots + - dvpinternalvirtualmachinesnapshotcontents + - dvpinternalvirtualmachinerestores verbs: - get - delete @@ -1039,9 +1039,9 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineexports + - dvpinternalvirtualmachineexports verbs: - get - delete @@ -1051,9 +1051,9 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineclones + - dvpinternalvirtualmachineclones verbs: - get - delete @@ -1063,12 +1063,12 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancetypes - - virtualmachineclusterinstancetypes - - virtualmachinepreferences - - virtualmachineclusterpreferences + - dvpinternalvirtualmachineinstancetypes + - dvpinternalvirtualmachineclusterinstancetypes + - dvpinternalvirtualmachinepreferences + - dvpinternalvirtualmachineclusterpreferences verbs: - get - delete @@ -1078,9 +1078,9 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinepools + - dvpinternalvirtualmachinepools verbs: - get - delete @@ -1090,16 +1090,16 @@ rules: - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - kubevirts + - dvpinternalkubevirts verbs: - get - list - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - migrationpolicies + - dvpinternalmigrationpolicies verbs: - get - list @@ -1120,67 +1120,67 @@ rules: verbs: - update - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines - - virtualmachineinstances - - virtualmachineinstancepresets - - virtualmachineinstancereplicasets - - virtualmachineinstancemigrations + - dvpinternalvirtualmachines + - dvpinternalvirtualmachineinstances + - dvpinternalvirtualmachineinstancepresets + - dvpinternalvirtualmachineinstancereplicasets + - dvpinternalvirtualmachineinstancemigrations verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinesnapshots - - virtualmachinesnapshotcontents - - virtualmachinerestores + - dvpinternalvirtualmachinesnapshots + - dvpinternalvirtualmachinesnapshotcontents + - dvpinternalvirtualmachinerestores verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineexports + - dvpinternalvirtualmachineexports verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineclones + - dvpinternalvirtualmachineclones verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachineinstancetypes - - virtualmachineclusterinstancetypes - - virtualmachinepreferences - - virtualmachineclusterpreferences + - dvpinternalvirtualmachineinstancetypes + - dvpinternalvirtualmachineclusterinstancetypes + - dvpinternalvirtualmachinepreferences + - dvpinternalvirtualmachineclusterpreferences verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachinepools + - dvpinternalvirtualmachinepools verbs: - get - list - watch - deletecollection - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - migrationpolicies + - dvpinternalmigrationpolicies verbs: - get - list diff --git a/templates/kubevirt/vmi-router/rbac-for-us.yaml b/templates/kubevirt/vmi-router/rbac-for-us.yaml index ca191d4e4..4e5ad8411 100644 --- a/templates/kubevirt/vmi-router/rbac-for-us.yaml +++ b/templates/kubevirt/vmi-router/rbac-for-us.yaml @@ -14,9 +14,9 @@ metadata: {{- include "helm_lib_module_labels" (list . (dict "app" "vmi-router")) | nindent 2 }} rules: - apiGroups: - - x.virtualization.deckhouse.io + - virtualization.deckhouse.io resources: - - virtualmachineinstances + - virtualmachines verbs: - get - list diff --git a/templates/pre-delete-hook/rbac-for-us.yaml b/templates/pre-delete-hook/rbac-for-us.yaml index 96bf862c9..84b4d0f43 100644 --- a/templates/pre-delete-hook/rbac-for-us.yaml +++ b/templates/pre-delete-hook/rbac-for-us.yaml @@ -15,10 +15,10 @@ metadata: {{- include "helm_lib_module_labels" (list . (dict "app" "virtualization-pre-delete-hook")) | nindent 2 }} rules: - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - cdis - - kubevirts + - dvpinternalcdis + - dvpinternalkubevirts verbs: - get - delete diff --git a/templates/user-authz-cluster-roles.yaml b/templates/user-authz-cluster-roles.yaml index 086e499b9..a846d0f30 100644 --- a/templates/user-authz-cluster-roles.yaml +++ b/templates/user-authz-cluster-roles.yaml @@ -10,14 +10,14 @@ rules: - apiGroups: - virtualization.deckhouse.io resources: - - virtualmachinedisks - - virtualmachineimages + - virtualdisks + - virtualimages - virtualmachinecpumodels - virtualmachineipaddressleases - virtualmachineipaddressclaims - virtualmachineblockdeviceattachments - virtualmachines - - clustervirtualmachineimages + - clustervirtualimages verbs: - get - list @@ -69,8 +69,8 @@ rules: - apiGroups: - virtualization.deckhouse.io resources: - - virtualmachinedisks - - virtualmachineimages + - virtualdisks + - virtualimages - virtualmachinecpumodels - virtualmachineipaddressleases - virtualmachineipaddressclaims @@ -94,7 +94,7 @@ rules: - apiGroups: - virtualization.deckhouse.io resources: - - clustervirtualmachineimages + - clustervirtualimages verbs: - create - delete diff --git a/templates/virtualization-controller/_helpers.tpl b/templates/virtualization-controller/_helpers.tpl index 00cbe7644..529e96ec1 100644 --- a/templates/virtualization-controller/_helpers.tpl +++ b/templates/virtualization-controller/_helpers.tpl @@ -1,5 +1,7 @@ {{- define "virtualization-controller.envs" -}} {{- $registry := include "dvcr.get_registry" (list .) }} +- name: KUBECONFIG + value: "/kubeconfig.local/proxy.kubeconfig" - name: VERBOSITY value: "3" - name: FORCE_BRIDGE_NETWORK_BINDING diff --git a/templates/virtualization-controller/deployment.yaml b/templates/virtualization-controller/deployment.yaml index 9f86fe578..3ebfcc4e5 100644 --- a/templates/virtualization-controller/deployment.yaml +++ b/templates/virtualization-controller/deployment.yaml @@ -45,6 +45,8 @@ metadata: name: virtualization-controller namespace: d8-{{ .Chart.Name }} {{- include "helm_lib_module_labels" (list . (dict "app" "virtualization-controller")) | nindent 2 }} + annotations: + kubectl.kubernetes.io/default-container: virtualization-controller spec: {{- include "helm_lib_deployment_strategy_and_replicas_for_ha" . | nindent 2 }} revisionHistoryLimit: 2 @@ -60,12 +62,32 @@ spec: spec: {{ include "helm_lib_pod_anti_affinity_for_ha" (list . (dict "app" "virtualization-controller")) | nindent 6 }} containers: + - name: proxy + image: {{ include "helm_lib_module_image" (list . "kubeApiProxy") }} + imagePullPolicy: IfNotPresent + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 12 }} + {{- if not ( .Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "virtualization_controller_resources" . | nindent 12 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File - name: virtualization-controller image: {{ include "helm_lib_module_image" (list . "virtualizationController") }} imagePullPolicy: Always volumeMounts: - mountPath: /tmp/k8s-webhook-server/serving-certs name: admission-webhook-secret + - mountPath: /kubeconfig.local + name: kube-api-proxy-kubeconfig ports: - containerPort: 9443 name: controller @@ -80,6 +102,7 @@ spec: {{- include "virtualization_controller_resources" . | nindent 12 }} {{- end }} env: {{ include "virtualization-controller.envs" . | nindent 12 }} + dnsPolicy: ClusterFirst serviceAccountName: virtualization-controller {{- include "helm_lib_priority_class" (tuple . "system-cluster-critical") | nindent 6 }} @@ -89,3 +112,6 @@ spec: - name: admission-webhook-secret secret: secretName: virtualization-controller-tls + - name: kube-api-proxy-kubeconfig + configMap: + name: kube-api-proxy-kubeconfig diff --git a/templates/virtualization-controller/rbac-for-us.yaml b/templates/virtualization-controller/rbac-for-us.yaml index f7d4ef69c..ad11ad77a 100644 --- a/templates/virtualization-controller/rbac-for-us.yaml +++ b/templates/virtualization-controller/rbac-for-us.yaml @@ -87,9 +87,9 @@ rules: - create - patch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - datavolumes + - dvpinternaldatavolumes verbs: - get - create @@ -98,10 +98,10 @@ rules: - watch - list - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines - - virtualmachineinstances + - dvpinternalvirtualmachines + - dvpinternalvirtualmachineinstances verbs: - get - watch @@ -111,17 +111,17 @@ rules: - list - delete - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - kubevirts + - dvpinternalkubevirts verbs: - get - list - watch - apiGroups: - - x.virtualization.deckhouse.io + - internal.virtualization.deckhouse.io resources: - - virtualmachines/status + - dvpinternalvirtualmachines/status verbs: - patch - update @@ -137,15 +137,15 @@ rules: - apiGroups: - virtualization.deckhouse.io resources: - - virtualmachinedisks + - virtualdisks - virtualmachinedisksnapshots - - virtualmachineimages + - virtualimages - virtualmachinecpumodels - virtualmachineipaddressleases - virtualmachineipaddressclaims - virtualmachineblockdeviceattachments - virtualmachines - - clustervirtualmachineimages + - clustervirtualimages - virtualmachineoperations verbs: - create @@ -158,12 +158,12 @@ rules: - apiGroups: - virtualization.deckhouse.io resources: - - virtualmachinedisks/finalizers + - virtualdisks/finalizers - virtualmachinedisksnapshots/finalizers - - virtualmachineimages/finalizers + - virtualimages/finalizers - virtualmachineblockdeviceattachments/finalizers - virtualmachines/finalizers - - clustervirtualmachineimages/finalizers + - clustervirtualimages/finalizers - virtualmachinecpumodels/finalizers - virtualmachineipaddressleases/finalizers - virtualmachineipaddressclaims/finalizers @@ -171,12 +171,12 @@ rules: - virtualmachineipaddressclaims/status - virtualmachinecpumodels/status - virtualmachineipaddressleases/status - - virtualmachinedisks/status + - virtualdisks/status - virtualmachinedisksnapshots/status - - virtualmachineimages/status + - virtualimages/status - virtualmachineblockdeviceattachments/status - virtualmachines/status - - clustervirtualmachineimages/status + - clustervirtualimages/status - virtualmachineoperations/status verbs: - patch diff --git a/templates/virtualization-controller/validation-webhook.yaml b/templates/virtualization-controller/validation-webhook.yaml index 06f2693c8..dc71ac4ee 100644 --- a/templates/virtualization-controller/validation-webhook.yaml +++ b/templates/virtualization-controller/validation-webhook.yaml @@ -25,13 +25,13 @@ webhooks: - apiGroups: ["virtualization.deckhouse.io"] apiVersions: ["v1alpha2"] operations: ["CREATE", "UPDATE"] - resources: ["virtualmachinedisks"] + resources: ["virtualdisks"] scope: "Namespaced" clientConfig: service: namespace: d8-{{ .Chart.Name }} name: virtualization-controller - path: /validate-virtualization-deckhouse-io-v1alpha2-virtualmachinedisk + path: /validate-virtualization-deckhouse-io-v1alpha2-virtualdisk port: 443 caBundle: | {{ .Values.virtualization.internal.controller.cert.ca }} diff --git a/tests/e2e/disks_test.go b/tests/e2e/disks_test.go index 7eeb670e1..b1c2d86a0 100644 --- a/tests/e2e/disks_test.go +++ b/tests/e2e/disks_test.go @@ -2,10 +2,12 @@ package e2e import ( "fmt" - kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" + "path" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "path" + + kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) const ( @@ -40,10 +42,12 @@ var _ = Describe("Disks", func() { res := kubectl.Get(filepath, kc.GetOptions{ Output: "jsonpath={.status.uploadCommand}", }) + Expect(res.Error()).NotTo(HaveOccurred(), "get failed upload.\n%s", res.StdErr()) - subCMD := fmt.Sprintf("run -n %s --restart=Never -i --tty %s --image=%s -- %s", conf.Namespace, UploadHelpPod, conf.Disks.UploadHelperImage, res.StdOut()) + subCMD := fmt.Sprintf("run -n %s --restart=Never -i --tty %s --image=%s -- %s", conf.Namespace, UploadHelpPod, conf.Disks.UploadHelperImage, res.StdOut()+" -k") + res = kubectl.RawCommand(subCMD, LongWaitDuration) - Expect(res.Error()).NotTo(HaveOccurred(), "craete pod upload helper failed.\n%s", res.StdErr()) + Expect(res.Error()).NotTo(HaveOccurred(), "create pod upload helper failed.\n%s", res.StdErr()) For := "jsonpath={.status.phase}=" + PhaseSucceeded WaitResource(kc.ResourcePod, UploadHelpPod, For, LongWaitDuration) CheckField(kc.ResourcePod, UploadHelpPod, "jsonpath={.status.phase}", PhaseSucceeded) @@ -52,7 +56,7 @@ var _ = Describe("Disks", func() { ItChekStatusPhaseFromFile(filepath, PhaseReady) } - Context("CVMI", Ordered, ContinueOnFailure, func() { + Context("CVI", Ordered, ContinueOnFailure, func() { AfterAll(func() { By("Removing resources for cvmi tests") kubectl.Delete(conf.Disks.CvmiTestDataDir, kc.DeleteOptions{}) @@ -93,7 +97,7 @@ var _ = Describe("Disks", func() { CheckProgress(filepath) }) }) - Context("VMI", Ordered, ContinueOnFailure, func() { + Context("VI", Ordered, ContinueOnFailure, func() { AfterAll(func() { By("Removing resources for vmi tests") kubectl.Delete(conf.Disks.VmiTestDataDir, kc.DeleteOptions{}) @@ -134,7 +138,7 @@ var _ = Describe("Disks", func() { CheckProgress(filepath) }) }) - Context("VMD", Ordered, ContinueOnFailure, func() { + Context("VD", Ordered, ContinueOnFailure, func() { AfterAll(func() { By("Removing resources for vmd tests") kubectl.Delete(conf.Disks.VmdTestDataDir, kc.DeleteOptions{}) diff --git a/tests/e2e/ipam_test.go b/tests/e2e/ipam_test.go index de5e631e9..061c5cc51 100644 --- a/tests/e2e/ipam_test.go +++ b/tests/e2e/ipam_test.go @@ -1,10 +1,12 @@ package e2e import ( - kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" + "path" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "path" + + kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) func ipamPath(file string) string { @@ -18,7 +20,7 @@ var _ = Describe("Ipam", func() { kubectl.Delete(conf.Ipam.TestDataDir, kc.DeleteOptions{}) }) GetLeasNameFromClaim := func(manifestClaim string) string { - res := kubectl.Get(manifestClaim, kc.GetOptions{Output: "jsonpath={.spec.leaseName}"}) + res := kubectl.Get(manifestClaim, kc.GetOptions{Output: "jsonpath={.spec.virtualMachineIPAddressLease}"}) Expect(res.Error()).NotTo(HaveOccurred(), "failed get vmip from file %s.\n%s", manifestClaim, res.StdErr()) return res.StdOut() } diff --git a/tests/e2e/testdata/cvmi/cvmi_containerimage.yaml b/tests/e2e/testdata/cvmi/cvmi_containerimage.yaml index db11e3d6f..3b7d72eb7 100644 --- a/tests/e2e/testdata/cvmi/cvmi_containerimage.yaml +++ b/tests/e2e/testdata/cvmi/cvmi_containerimage.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-cvmi-containerimage spec: diff --git a/tests/e2e/testdata/cvmi/cvmi_cvmi.yaml b/tests/e2e/testdata/cvmi/cvmi_cvmi.yaml index 5b56525bb..a9e23062a 100644 --- a/tests/e2e/testdata/cvmi/cvmi_cvmi.yaml +++ b/tests/e2e/testdata/cvmi/cvmi_cvmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-cvmi-cvmi-old spec: @@ -9,11 +9,12 @@ spec: url: "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-cvmi-cvmi-new spec: dataSource: - type: "ClusterVirtualMachineImage" - clusterVirtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "ClusterVirtualImage" name: test-cvmi-cvmi-old diff --git a/tests/e2e/testdata/cvmi/cvmi_http.yaml b/tests/e2e/testdata/cvmi/cvmi_http.yaml index 9a7de6b46..2b40579b3 100644 --- a/tests/e2e/testdata/cvmi/cvmi_http.yaml +++ b/tests/e2e/testdata/cvmi/cvmi_http.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-cvmi-http spec: diff --git a/tests/e2e/testdata/cvmi/cvmi_upload.yaml b/tests/e2e/testdata/cvmi/cvmi_upload.yaml index d92f6d9d4..01d7737a8 100644 --- a/tests/e2e/testdata/cvmi/cvmi_upload.yaml +++ b/tests/e2e/testdata/cvmi/cvmi_upload.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-cvmi-upload spec: diff --git a/tests/e2e/testdata/cvmi/cvmi_vmi.yaml b/tests/e2e/testdata/cvmi/cvmi_vmi.yaml index cf36885bf..8a8fc4b5e 100644 --- a/tests/e2e/testdata/cvmi/cvmi_vmi.yaml +++ b/tests/e2e/testdata/cvmi/cvmi_vmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-cvmi-vmi namespace: test-d8-virtualization @@ -12,12 +12,13 @@ spec: url: "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-cvmi-vmi spec: dataSource: - type: "VirtualMachineImage" - virtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "VirtualImage" name: test-cvmi-vmi namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vm/boot/vm_cvmi.yaml b/tests/e2e/testdata/vm/boot/vm_cvmi.yaml index 9e6172bc5..99396994c 100644 --- a/tests/e2e/testdata/vm/boot/vm_cvmi.yaml +++ b/tests/e2e/testdata/vm/boot/vm_cvmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-vm-boot-cvmi spec: @@ -24,7 +24,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: ClusterVirtualMachineImage - clusterVirtualMachineImage: - name: test-vm-boot-cvmi + blockDeviceRefs: + - kind: ClusterVirtualImage + name: test-vm-boot-cvmi diff --git a/tests/e2e/testdata/vm/boot/vm_vmd.yaml b/tests/e2e/testdata/vm/boot/vm_vmd.yaml index 4dc0f6fb1..654fd9901 100644 --- a/tests/e2e/testdata/vm/boot/vm_vmd.yaml +++ b/tests/e2e/testdata/vm/boot/vm_vmd.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vm-boot-vmd namespace: test-d8-virtualization @@ -27,7 +27,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: test-vm-boot-vmd + blockDeviceRefs: + - kind: VirtualDisk + name: test-vm-boot-vmd diff --git a/tests/e2e/testdata/vm/boot/vm_vmi.yaml b/tests/e2e/testdata/vm/boot/vm_vmi.yaml index 54e09a50d..bdd54a49a 100644 --- a/tests/e2e/testdata/vm/boot/vm_vmi.yaml +++ b/tests/e2e/testdata/vm/boot/vm_vmi.yaml @@ -13,7 +13,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image diff --git a/tests/e2e/testdata/vm/connectivity/vm1_connectivity.yaml b/tests/e2e/testdata/vm/connectivity/vm1_connectivity.yaml index 579d676b6..438a355f4 100644 --- a/tests/e2e/testdata/vm/connectivity/vm1_connectivity.yaml +++ b/tests/e2e/testdata/vm/connectivity/vm1_connectivity.yaml @@ -1,6 +1,6 @@ --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-connectivity-vmd-vmi-1 namespace: test-d8-virtualization @@ -8,8 +8,9 @@ spec: persistentVolumeClaim: size: 4Gi dataSource: - type: "VirtualMachineImage" - virtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "VirtualImage" name: test-vm-image --- apiVersion: virtualization.deckhouse.io/v1alpha2 @@ -30,11 +31,10 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: test-connectivity-vmd-vmi-1 - virtualMachineIPAddressClaimName: test-connectivity-ipam-vm1 + blockDeviceRefs: + - kind: VirtualDisk + name: test-connectivity-vmd-vmi-1 + virtualMachineIPAddressClaim: test-connectivity-ipam-vm1 provisioning: type: UserData userData: | diff --git a/tests/e2e/testdata/vm/connectivity/vm2_connectivity.yaml b/tests/e2e/testdata/vm/connectivity/vm2_connectivity.yaml index 34a7059f7..d86b7fe66 100644 --- a/tests/e2e/testdata/vm/connectivity/vm2_connectivity.yaml +++ b/tests/e2e/testdata/vm/connectivity/vm2_connectivity.yaml @@ -1,6 +1,6 @@ --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-connectivity-vmd-vmi-2 namespace: test-d8-virtualization @@ -8,8 +8,9 @@ spec: persistentVolumeClaim: size: 4Gi dataSource: - type: "VirtualMachineImage" - virtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "VirtualImage" name: test-vm-image --- apiVersion: virtualization.deckhouse.io/v1alpha2 @@ -30,11 +31,10 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: test-connectivity-vmd-vmi-2 - virtualMachineIPAddressClaimName: test-connectivity-ipam-vm2 + blockDeviceRefs: + - kind: VirtualDisk + name: test-connectivity-vmd-vmi-2 + virtualMachineIPAddressClaim: test-connectivity-ipam-vm2 provisioning: type: UserData userData: | diff --git a/tests/e2e/testdata/vm/cvmi.yaml b/tests/e2e/testdata/vm/cvmi.yaml index a6b0d7acf..4508fe2dc 100644 --- a/tests/e2e/testdata/vm/cvmi.yaml +++ b/tests/e2e/testdata/vm/cvmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: linux-cvmi-http spec: diff --git a/tests/e2e/testdata/vm/image.yaml b/tests/e2e/testdata/vm/image.yaml index b4866640c..37cf9ec4c 100644 --- a/tests/e2e/testdata/vm/image.yaml +++ b/tests/e2e/testdata/vm/image.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vm-image namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vm/provisioning/vm_provisioning_secret.yaml b/tests/e2e/testdata/vm/provisioning/vm_provisioning_secret.yaml index cddd52862..6eb56f88b 100644 --- a/tests/e2e/testdata/vm/provisioning/vm_provisioning_secret.yaml +++ b/tests/e2e/testdata/vm/provisioning/vm_provisioning_secret.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: Secret metadata: name: test-vm-provisioning-secret + namespace: test-d8-virtualization type: Opaque data: userdata: I2Nsb3VkLWNvbmZpZwp1c2VyczoKLSBkZWZhdWx0Ci0gbmFtZTogdXNlcgogIHBhc3N3ZDogIiQ2JHFyRU9uVmI5SHNxYzFUSkokR0dTb3BETUcwbFBGQjk5ZHF0WExCN1kyVjZtZDhoT2l4c3ZsOEI1Z3RCVEVBUUlMUEs1UW9XeS4ybmhHOGlBNlZhdjdlb2VocXp6eWxEYmowdy5CVS8iICMgInBhc3N3b3JkIgogIHNoZWxsOiAvYmluL2Jhc2gKICBsb2NrLXBhc3N3ZDogZmFsc2UKICBzc2hfcHdhdXRoOiBUcnVlCiAgY2hwYXNzd2Q6IHsgZXhwaXJlOiBGYWxzZSB9CiAgc3VkbzogQUxMPShBTEwpIE5PUEFTU1dEOkFMTAogIGdyb3VwczogdXNlcnMsIGFkbWluCiAgc3NoX2F1dGhvcml6ZWRfa2V5czoKICAgIC0gJ3NzaC1lZDI1NTE5IEFBQUFDM056YUMxbFpESTFOVEU1QUFBQUlGeGNYSG13YUduSjhzY0phRU41UnprbEJQWnBWU2ljNEdkYUFzS2pRb2VBIHlvdXJfZW1haWxAZXhhbXBsZS5jb20nCnNzaF9kZWxldGVrZXlzOiBmYWxzZQo= @@ -22,11 +23,11 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image provisioning: - type: UserDataSecret - userDataSecretRef: + type: UserDataRef + userDataRef: + kind: Secret name: test-vm-provisioning-secret diff --git a/tests/e2e/testdata/vm/provisioning/vm_provisioning_useradata.yaml b/tests/e2e/testdata/vm/provisioning/vm_provisioning_useradata.yaml index fea5fe645..2dba3f8e0 100644 --- a/tests/e2e/testdata/vm/provisioning/vm_provisioning_useradata.yaml +++ b/tests/e2e/testdata/vm/provisioning/vm_provisioning_useradata.yaml @@ -13,10 +13,9 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image provisioning: type: UserData userData: | diff --git a/tests/e2e/testdata/vm/resources/vm_100.yaml b/tests/e2e/testdata/vm/resources/vm_100.yaml index de42444cd..3abd4e331 100644 --- a/tests/e2e/testdata/vm/resources/vm_100.yaml +++ b/tests/e2e/testdata/vm/resources/vm_100.yaml @@ -14,7 +14,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image diff --git a/tests/e2e/testdata/vm/resources/vm_25.yaml b/tests/e2e/testdata/vm/resources/vm_25.yaml index 34bea0c33..52bf0b5af 100644 --- a/tests/e2e/testdata/vm/resources/vm_25.yaml +++ b/tests/e2e/testdata/vm/resources/vm_25.yaml @@ -14,7 +14,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image diff --git a/tests/e2e/testdata/vm/resources/vm_50.yaml b/tests/e2e/testdata/vm/resources/vm_50.yaml index 2ceb670f3..a3b0d0100 100644 --- a/tests/e2e/testdata/vm/resources/vm_50.yaml +++ b/tests/e2e/testdata/vm/resources/vm_50.yaml @@ -14,7 +14,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image diff --git a/tests/e2e/testdata/vm/vm_graceperiod.yaml b/tests/e2e/testdata/vm/vm_graceperiod.yaml index 6f430f422..068d65749 100644 --- a/tests/e2e/testdata/vm/vm_graceperiod.yaml +++ b/tests/e2e/testdata/vm/vm_graceperiod.yaml @@ -13,8 +13,7 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image terminationGracePeriodSeconds: 5 diff --git a/tests/e2e/testdata/vm/vm_label_annotation.yaml b/tests/e2e/testdata/vm/vm_label_annotation.yaml index 6fbdb9796..44cc6ae19 100644 --- a/tests/e2e/testdata/vm/vm_label_annotation.yaml +++ b/tests/e2e/testdata/vm/vm_label_annotation.yaml @@ -13,7 +13,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image diff --git a/tests/e2e/testdata/vm/vm_priorityclassname.yaml b/tests/e2e/testdata/vm/vm_priorityclassname.yaml index 7783a6968..8a43f459e 100644 --- a/tests/e2e/testdata/vm/vm_priorityclassname.yaml +++ b/tests/e2e/testdata/vm/vm_priorityclassname.yaml @@ -21,8 +21,7 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image priorityClassName: test-high-priority diff --git a/tests/e2e/testdata/vm/vm_runpolicy.yaml b/tests/e2e/testdata/vm/vm_runpolicy.yaml index 9d97c8fe1..0f0d38151 100644 --- a/tests/e2e/testdata/vm/vm_runpolicy.yaml +++ b/tests/e2e/testdata/vm/vm_runpolicy.yaml @@ -13,7 +13,6 @@ spec: cores: 1 memory: size: 1Gi - blockDevices: - - type: VirtualMachineImage - virtualMachineImage: - name: test-vm-image + blockDeviceRefs: + - kind: VirtualImage + name: test-vm-image diff --git a/tests/e2e/testdata/vmd/vmd_blank.yaml b/tests/e2e/testdata/vmd/vmd_blank.yaml index d04f31e66..09ba82bf5 100644 --- a/tests/e2e/testdata/vmd/vmd_blank.yaml +++ b/tests/e2e/testdata/vmd/vmd_blank.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vmd-blank namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmd/vmd_containerimage.yaml b/tests/e2e/testdata/vmd/vmd_containerimage.yaml index f4478fa41..84d7456ad 100644 --- a/tests/e2e/testdata/vmd/vmd_containerimage.yaml +++ b/tests/e2e/testdata/vmd/vmd_containerimage.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vmd-containerimage namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmd/vmd_cvmi.yaml b/tests/e2e/testdata/vmd/vmd_cvmi.yaml index a300a5b52..1e13cfccb 100644 --- a/tests/e2e/testdata/vmd/vmd_cvmi.yaml +++ b/tests/e2e/testdata/vmd/vmd_cvmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-vmd-cvmi namespace: test-d8-virtualization @@ -11,7 +11,7 @@ spec: url: "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vmd-cvmi namespace: test-d8-virtualization @@ -19,6 +19,7 @@ spec: persistentVolumeClaim: size: 200Mi dataSource: - type: "ClusterVirtualMachineImage" - clusterVirtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "ClusterVirtualImage" name: test-vmd-cvmi diff --git a/tests/e2e/testdata/vmd/vmd_http.yaml b/tests/e2e/testdata/vmd/vmd_http.yaml index 7d1a7e7be..38f61d2d8 100644 --- a/tests/e2e/testdata/vmd/vmd_http.yaml +++ b/tests/e2e/testdata/vmd/vmd_http.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vmd-http namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmd/vmd_upload.yaml b/tests/e2e/testdata/vmd/vmd_upload.yaml index 987ad5c46..792c4f3d7 100644 --- a/tests/e2e/testdata/vmd/vmd_upload.yaml +++ b/tests/e2e/testdata/vmd/vmd_upload.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vmd-upload namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmd/vmd_vmi.yaml b/tests/e2e/testdata/vmd/vmd_vmi.yaml index 8e9395aea..460a5e12d 100644 --- a/tests/e2e/testdata/vmd/vmd_vmi.yaml +++ b/tests/e2e/testdata/vmd/vmd_vmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmd-vmi namespace: test-d8-virtualization @@ -12,7 +12,7 @@ spec: url: "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: test-vmd-vmi namespace: test-d8-virtualization @@ -20,6 +20,7 @@ spec: persistentVolumeClaim: size: 200Mi dataSource: - type: "VirtualMachineImage" - virtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "VirtualImage" name: test-vmd-vmi diff --git a/tests/e2e/testdata/vmi/vmi_containerimage.yaml b/tests/e2e/testdata/vmi/vmi_containerimage.yaml index b9faccf88..279172a52 100644 --- a/tests/e2e/testdata/vmi/vmi_containerimage.yaml +++ b/tests/e2e/testdata/vmi/vmi_containerimage.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmi-containerimage namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmi/vmi_cvmi.yaml b/tests/e2e/testdata/vmi/vmi_cvmi.yaml index 14acd5920..bf5021a00 100644 --- a/tests/e2e/testdata/vmi/vmi_cvmi.yaml +++ b/tests/e2e/testdata/vmi/vmi_cvmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: ClusterVirtualMachineImage +kind: ClusterVirtualImage metadata: name: test-vmi-cvmi spec: @@ -9,13 +9,14 @@ spec: url: "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmi-cvmi namespace: test-d8-virtualization spec: storage: ContainerRegistry dataSource: - type: "ClusterVirtualMachineImage" - clusterVirtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "ClusterVirtualImage" name: test-vmi-cvmi diff --git a/tests/e2e/testdata/vmi/vmi_http.yaml b/tests/e2e/testdata/vmi/vmi_http.yaml index 9f3a1ffb4..0fb676e1f 100644 --- a/tests/e2e/testdata/vmi/vmi_http.yaml +++ b/tests/e2e/testdata/vmi/vmi_http.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmi-http namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmi/vmi_upload.yaml b/tests/e2e/testdata/vmi/vmi_upload.yaml index 102da346b..13b96aaae 100644 --- a/tests/e2e/testdata/vmi/vmi_upload.yaml +++ b/tests/e2e/testdata/vmi/vmi_upload.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmi-upload namespace: test-d8-virtualization diff --git a/tests/e2e/testdata/vmi/vmi_vmi.yaml b/tests/e2e/testdata/vmi/vmi_vmi.yaml index 427ab4141..65ed1bdec 100644 --- a/tests/e2e/testdata/vmi/vmi_vmi.yaml +++ b/tests/e2e/testdata/vmi/vmi_vmi.yaml @@ -1,5 +1,5 @@ apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmi-vmi-old namespace: test-d8-virtualization @@ -12,13 +12,14 @@ spec: url: "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: test-vmi-vmi-new namespace: test-d8-virtualization spec: storage: ContainerRegistry dataSource: - type: "VirtualMachineImage" - virtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "VirtualImage" name: test-vmi-vmi-old diff --git a/tests/e2e/util_test.go b/tests/e2e/util_test.go index f86affa84..4fa3e6ee3 100644 --- a/tests/e2e/util_test.go +++ b/tests/e2e/util_test.go @@ -2,16 +2,18 @@ package e2e import ( "fmt" - "github.com/deckhouse/virtualization/tests/e2e/executor" - "github.com/deckhouse/virtualization/tests/e2e/helper" - kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" + "log" + "os" + "time" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "log" - "os" - "time" + + "github.com/deckhouse/virtualization/tests/e2e/executor" + "github.com/deckhouse/virtualization/tests/e2e/helper" + kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -138,13 +140,13 @@ type VirtualMachine struct { } type VirtualMachineSpec struct { - RunPolicy RunPolicy `json:"runPolicy"` - VirtualMachineIPAddressClaimName string `json:"virtualMachineIPAddressClaimName,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - PriorityClassName string `json:"priorityClassName"` - Tolerations []corev1.Toleration `json:"tolerations,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` - EnableParavirtualization bool `json:"enableParavirtualization,omitempty"` + RunPolicy RunPolicy `json:"runPolicy"` + VirtualMachineIPAddressClaim string `json:"virtualMachineIPAddressClaim,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + PriorityClassName string `json:"priorityClassName"` + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` + EnableParavirtualization bool `json:"enableParavirtualization,omitempty"` ApprovedChangeID string `json:"approvedChangeID,omitempty"` } diff --git a/tests/e2e/vm_test.go b/tests/e2e/vm_test.go index 5d1394fdf..17c31749b 100644 --- a/tests/e2e/vm_test.go +++ b/tests/e2e/vm_test.go @@ -3,17 +3,18 @@ package e2e import ( "encoding/json" "fmt" - kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" - virt "github.com/deckhouse/virtualization/tests/e2e/virtctl" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" "io/fs" - corev1 "k8s.io/api/core/v1" "path" "path/filepath" "strconv" "strings" "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + + kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) const ( @@ -92,15 +93,15 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { GetVmStatus(name, VMStatusRunning) }) } - When("VMI source", func() { + When("VI source", func() { manifest := vmPath("boot/vm_vmi.yaml") Test(manifest) }) - When("CVMI source", func() { + When("CVI source", func() { manifest := vmPath("boot/vm_cvmi.yaml") Test(manifest) }) - When("VMD source", func() { + When("VD source", func() { manifest := vmPath("boot/vm_vmd.yaml") Test(manifest) }) @@ -182,16 +183,17 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { }) Context("Provisioning", func() { - CheckSsh := func(vmName string) { - GinkgoHelper() - res := virtctl.SshCommand(vmName, "sudo whoami", virt.SshOptions{ - Namespace: conf.Namespace, - Username: "user", - IdenityFile: vmPath("provisioning/id_ed"), - }) - Expect(res.Error()).To(BeNil(), "check ssh failed for %s/%s.\n%s", conf.Namespace, vmName, res.StdErr()) - Expect(strings.TrimSpace(res.StdOut())).To(Equal("root")) - } + // TODO(refactor) from virtctl to d8 virtualization. + // CheckSsh := func(vmName string) { + // GinkgoHelper() + // res := virtctl.SshCommand(vmName, "sudo whoami", virt.SshOptions{ + // Namespace: conf.Namespace, + // Username: "user", + // IdenityFile: vmPath("provisioning/id_ed"), + // }) + // Expect(res.Error()).To(BeNil(), "check ssh failed for %s/%s.\n%s", conf.Namespace, vmName, res.StdErr()) + // Expect(strings.TrimSpace(res.StdOut())).To(Equal("root")) + // } Test := func(manifest string) { GinkgoHelper() @@ -205,9 +207,10 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { It("Wait vm running", func() { WaitVmStatus(name, VMStatusRunning) }) - It("Check ssh", func() { - CheckSsh(name) - }) + // TODO(refactor) from virtctl to d8 virtualization. + // It("Check ssh", func() { + // CheckSsh(name) + // }) } AfterAll(func() { By("Delete manifests") @@ -217,7 +220,7 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { manifest := vmPath("provisioning/vm_provisioning_useradata.yaml") Test(manifest) }) - When("UserDataSecretRef", func() { + When("UserDataRef", func() { manifest := vmPath("provisioning/vm_provisioning_secret.yaml") Test(manifest) }) diff --git a/tests/performance/bootstrapper.sh b/tests/performance/bootstrapper.sh index fbd1b1f86..362238539 100755 --- a/tests/performance/bootstrapper.sh +++ b/tests/performance/bootstrapper.sh @@ -71,12 +71,12 @@ function destroy() { case "${RESOURCES}" in "all") kubectl wait -n "${NAMESPACE}" --for=delete vm -l vm="${RESOURCES_PREFIX}" - kubectl wait -n "${NAMESPACE}" --for=delete vmd -l vm="${RESOURCES_PREFIX}" - kubectl wait -n "${NAMESPACE}" --for=delete vmi -l vm="${RESOURCES_PREFIX}" + kubectl wait -n "${NAMESPACE}" --for=delete vd -l vm="${RESOURCES_PREFIX}" + kubectl wait -n "${NAMESPACE}" --for=delete vi -l vm="${RESOURCES_PREFIX}" ;; "disks") - kubectl wait -n "${NAMESPACE}" --for=delete vmd -l vm="${RESOURCES_PREFIX}" - kubectl wait -n "${NAMESPACE}" --for=delete vmi -l vm="${RESOURCES_PREFIX}" + kubectl wait -n "${NAMESPACE}" --for=delete vd -l vm="${RESOURCES_PREFIX}" + kubectl wait -n "${NAMESPACE}" --for=delete vi -l vm="${RESOURCES_PREFIX}" ;; "vms") kubectl wait -n "${NAMESPACE}" --for=delete vm -l vm="${RESOURCES_PREFIX}" diff --git a/tests/performance/templates/vmds.yaml b/tests/performance/templates/vmds.yaml index 152387f4b..6221df21b 100644 --- a/tests/performance/templates/vmds.yaml +++ b/tests/performance/templates/vmds.yaml @@ -1,6 +1,6 @@ {{- if or (eq .Values.resources "disks") (eq .Values.resources "all") }} apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineImage +kind: VirtualImage metadata: name: {{ $.Values.resourcesPrefix }} namespace: {{ $.Release.Namespace }} @@ -16,7 +16,7 @@ spec: {{- range until $count }} --- apiVersion: virtualization.deckhouse.io/v1alpha2 -kind: VirtualMachineDisk +kind: VirtualDisk metadata: name: {{ $.Values.resourcesPrefix }}-{{ . }} namespace: {{ $.Release.Namespace }} @@ -26,11 +26,12 @@ spec: persistentVolumeClaim: size: {{ $.Values.diskSize }} {{- if $.Values.storageClass }} - storageClassName: {{ $.Values.storageClass }} + storageClass: {{ $.Values.storageClass }} {{- end }} dataSource: - type: "VirtualMachineImage" - virtualMachineImage: + type: "ObjectRef" + objectRef: + kind: "VirtualImage" name: {{ $.Values.resourcesPrefix }} {{- end }} {{- end }} diff --git a/tests/performance/templates/vms.yaml b/tests/performance/templates/vms.yaml index 9b48a848d..4e9f2407c 100644 --- a/tests/performance/templates/vms.yaml +++ b/tests/performance/templates/vms.yaml @@ -22,13 +22,13 @@ spec: memory: {{- toYaml . | nindent 4 }} {{- end }} - blockDevices: - - type: VirtualMachineDisk - virtualMachineDisk: - name: {{ $.Values.resourcesPrefix }}-{{ . }} + blockDeviceRefs: + - kind: VirtualDisk + name: {{ $.Values.resourcesPrefix }}-{{ . }} provisioning: - type: UserDataSecret - userDataSecretRef: + type: UserDataRef + userDataRef: + kind: Secret name: {{ $.Values.resourcesPrefix }}-cloud-init {{- end }} {{- end }} \ No newline at end of file