diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..60cdf5884c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,12 @@ +# Tell GitHub about generated files + +# deepcopy and conversion-gen +zz_generated.* linguist-generated=true + +# Generated parts of manifests +/config/crd/bases/infrastructure.cluster.x-k8s.io_*.yaml linguist-generated=true +/config/webhook/manifests.yaml linguist-generated=true +/config/rbac/role.yaml linguist-generated=true + +# Generated API docs +/docs/book/src/api/*/** linguist-generated=true diff --git a/.gitignore b/.gitignore index da5756bd21..d2a0fe7cbf 100644 --- a/.gitignore +++ b/.gitignore @@ -173,6 +173,7 @@ sshuttle.pid # Book docs/book/book/ +!docs/book/gen-crd-api-reference-docs/config.json # venv .venv diff --git a/.golangci.yml b/.golangci.yml index dd62b87cb9..7e3d5aac16 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -101,6 +101,8 @@ linters-settings: - pkg: sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6 alias: infrav1alpha6 - pkg: sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7 + alias: infrav1alpha7 + - pkg: sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1 alias: infrav1 - pkg: sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors alias: capoerrors @@ -166,11 +168,14 @@ issues: - linters: - revive text: "var-naming: don't use underscores in Go names;" - path: .*(api|types)\/.*\/.*conversion.*\.go$ - linters: - stylecheck text: "ST1003: should not use underscores in Go names;" - path: .*(api|types)\/.*\/.*conversion.*\.go$ + path: (api\/.*|pkg/utils/optional)\/.*conversion.*\.go$ + - linters: + - stylecheck + text: "ST1003: should not use underscores in Go names;" + path: pkg/utils/conversioncommon/.*.go run: timeout: 10m diff --git a/Dockerfile b/Dockerfile index 03a064bd63..9cfb9287cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ # limitations under the License. # Build the manager binary -FROM golang:1.20.10 as builder +FROM golang:1.22.0 as builder WORKDIR /workspace # Run this with docker build --build_arg goproxy=$(go env GOPROXY) to override the goproxy diff --git a/Makefile b/Makefile index 28f6ac080e..525b1c894b 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ KUSTOMIZE := $(TOOLS_BIN_DIR)/kustomize MOCKGEN := $(TOOLS_BIN_DIR)/mockgen RELEASE_NOTES := $(TOOLS_BIN_DIR)/release-notes SETUP_ENVTEST := $(TOOLS_BIN_DIR)/setup-envtest +GEN_CRD_API_REFERENCE_DOCS := $(TOOLS_BIN_DIR)/gen-crd-api-reference-docs # Kubebuilder export KUBEBUILDER_ENVTEST_KUBERNETES_VERSION ?= 1.28.0 @@ -132,13 +133,15 @@ ifdef KUBEBUILDER_ASSETS_DIR setup_envtest_extra_args += --bin-dir $(KUBEBUILDER_ASSETS_DIR) endif +.PHONY: kubebuilder_assets +kubebuilder_assets: $(SETUP_ENVTEST) + @echo Fetching assets for $(KUBEBUILDER_ENVTEST_KUBERNETES_VERSION) + $(eval KUBEBUILDER_ASSETS ?= $(shell $(SETUP_ENVTEST) use --use-env -p path $(setup_envtest_extra_args) $(KUBEBUILDER_ENVTEST_KUBERNETES_VERSION))) + .PHONY: test -test: $(SETUP_ENVTEST) ## Run tests - set -xeuf -o pipefail; \ - if [ -z "$(KUBEBUILDER_ASSETS)" ]; then \ - KUBEBUILDER_ASSETS=`$(SETUP_ENVTEST) use --use-env -p path $(setup_envtest_extra_args) $(KUBEBUILDER_ENVTEST_KUBERNETES_VERSION)`; \ - fi; \ - KUBEBUILDER_ASSETS="$$KUBEBUILDER_ASSETS" go test -v ./... $(TEST_ARGS) +TEST_PATHS ?= ./... +test: kubebuilder_assets + KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" go test -v $(TEST_PATHS) $(TEST_ARGS) E2E_TEMPLATES_DIR=test/e2e/data/infrastructure-openstack E2E_KUSTOMIZE_DIR=test/e2e/data/kustomize @@ -148,8 +151,8 @@ E2E_NO_ARTIFACT_TEMPLATES_DIR=test/e2e/data/infrastructure-openstack-no-artifact .PHONY: e2e-templates e2e-templates: ## Generate cluster templates for e2e tests e2e-templates: $(addprefix $(E2E_NO_ARTIFACT_TEMPLATES_DIR)/, \ - cluster-template-v1alpha5.yaml \ cluster-template-v1alpha6.yaml \ + cluster-template-v1alpha7.yaml \ cluster-template-md-remediation.yaml \ cluster-template-kcp-remediation.yaml \ cluster-template-multi-az.yaml \ @@ -157,7 +160,9 @@ e2e-templates: $(addprefix $(E2E_NO_ARTIFACT_TEMPLATES_DIR)/, \ cluster-template-without-lb.yaml \ cluster-template.yaml \ cluster-template-flatcar.yaml \ - cluster-template-k8s-upgrade.yaml) + cluster-template-k8s-upgrade.yaml \ + cluster-template-flatcar-sysext.yaml \ + cluster-template-no-bastion.yaml) # Currently no templates that require CI artifacts # $(addprefix $(E2E_TEMPLATES_DIR)/, add-templates-here.yaml) \ @@ -167,15 +172,16 @@ $(E2E_NO_ARTIFACT_TEMPLATES_DIR)/cluster-template.yaml: $(E2E_KUSTOMIZE_DIR)/wit $(E2E_NO_ARTIFACT_TEMPLATES_DIR)/cluster-template-%.yaml: $(E2E_KUSTOMIZE_DIR)/% $(KUSTOMIZE) FORCE $(KUSTOMIZE) build "$<" > "$@" -e2e-prerequisites: $(GINKGO) e2e-templates e2e-image test-e2e-image-prerequisites ## Build all artifacts required by e2e tests +e2e-prerequisites: e2e-templates e2e-image test-e2e-image-prerequisites ## Build all artifacts required by e2e tests # Can be run manually, e.g. via: # export OPENSTACK_CLOUD_YAML_FILE="$(pwd)/clouds.yaml" # E2E_GINKGO_ARGS="-stream -focus='default'" E2E_ARGS="-use-existing-cluster='true'" make test-e2e E2E_GINKGO_ARGS ?= .PHONY: test-e2e ## Run e2e tests using clusterctl -test-e2e: e2e-prerequisites ## Run e2e tests +test-e2e: $(GINKGO) e2e-prerequisites ## Run e2e tests time $(GINKGO) -fail-fast -trace -timeout=3h -show-node-events -v -tags=e2e -nodes=$(E2E_GINKGO_PARALLEL) \ + --output-dir="$(ARTIFACTS)" --junit-report="junit.e2e_suite.1.xml" \ -focus="$(E2E_GINKGO_FOCUS)" $(_SKIP_ARGS) $(E2E_GINKGO_ARGS) ./test/e2e/suites/e2e/... -- \ -config-path="$(E2E_CONF_PATH)" -artifacts-folder="$(ARTIFACTS)" \ -data-folder="$(E2E_DATA_DIR)" $(E2E_ARGS) @@ -197,7 +203,7 @@ CONFORMANCE_E2E_ARGS ?= -kubetest.config-file=$(KUBETEST_CONF_PATH) CONFORMANCE_E2E_ARGS += $(E2E_ARGS) CONFORMANCE_GINKGO_ARGS ?= -stream .PHONY: test-conformance -test-conformance: e2e-prerequisites ## Run clusterctl based conformance test on workload cluster (requires Docker). +test-conformance: $(GINKGO) e2e-prerequisites ## Run clusterctl based conformance test on workload cluster (requires Docker). time $(GINKGO) -trace -show-node-events -v -tags=e2e -focus="conformance" $(CONFORMANCE_GINKGO_ARGS) ./test/e2e/suites/conformance/... -- -config-path="$(E2E_CONF_PATH)" -artifacts-folder="$(ARTIFACTS)" --data-folder="$(E2E_DATA_DIR)" $(CONFORMANCE_E2E_ARGS) test-conformance-fast: ## Run clusterctl based conformance test on workload cluster (requires Docker) using a subset of the conformance suite in parallel. @@ -244,30 +250,39 @@ modules: ## Runs go mod to ensure proper vendoring. cd $(TOOLS_DIR); go mod tidy .PHONY: generate -generate: ## Generate code - $(MAKE) generate-go - $(MAKE) generate-manifests +generate: templates generate-controller-gen generate-conversion-gen generate-go generate-manifests generate-api-docs ## Generate all generated code .PHONY: generate-go generate-go: $(MOCKGEN) - $(MAKE) -B $(CONTROLLER_GEN) $(CONVERSION_GEN) + go generate ./... + +.PHONY: generate-controller-gen +generate-controller-gen: $(CONTROLLER_GEN) $(CONTROLLER_GEN) \ paths=./api/... \ object:headerFile=./hack/boilerplate/boilerplate.generatego.txt + +.PHONY: generate-conversion-gen +capo_module := sigs.k8s.io/cluster-api-provider-openstack +generate-conversion-gen: $(CONVERSION_GEN) $(CONVERSION_GEN) \ - --input-dirs=./api/v1alpha5 \ - --input-dirs=./api/v1alpha6 \ - --input-dirs=./api/v1alpha7 \ + --input-dirs=$(capo_module)/api/v1alpha5 \ + --input-dirs=$(capo_module)/api/v1alpha6 \ + --input-dirs=$(capo_module)/api/v1alpha7 \ + --extra-dirs=$(capo_module)/pkg/utils/optional \ + --extra-dirs=$(capo_module)/pkg/utils/conversioncommon \ --output-file-base=zz_generated.conversion \ + --trim-path-prefix=$(capo_module)/ \ --go-header-file=./hack/boilerplate/boilerplate.generatego.txt - go generate ./... .PHONY: generate-manifests generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc. $(CONTROLLER_GEN) \ paths=./api/... \ crd:crdVersions=v1 \ - output:crd:dir=$(CRD_ROOT) \ + output:crd:dir=$(CRD_ROOT) + $(CONTROLLER_GEN) \ + paths=./pkg/webhooks/... \ output:webhook:dir=$(WEBHOOK_ROOT) \ webhook $(CONTROLLER_GEN) \ @@ -276,6 +291,15 @@ generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc. output:rbac:dir=$(RBAC_ROOT) \ rbac:roleName=manager-role +.PHONY: generate-api-docs +generate-api-docs: generate-api-docs-v1beta1 generate-api-docs-v1alpha7 generate-api-docs-v1alpha6 generate-api-docs-v1alpha1 +generate-api-docs-%: $(GEN_CRD_API_REFERENCE_DOCS) FORCE + $(GEN_CRD_API_REFERENCE_DOCS) \ + -api-dir=./api/$* \ + -config=./docs/book/gen-crd-api-reference-docs/config.json \ + -template-dir=./docs/book/gen-crd-api-reference-docs/template \ + -out-file=./docs/book/src/api/$*/api.md + ## -------------------------------------- ##@ Docker ## -------------------------------------- @@ -404,12 +428,13 @@ release-notes: $(RELEASE_NOTES) ## Generate release notes templates: ## Generate cluster templates templates: templates/cluster-template.yaml \ templates/cluster-template-without-lb.yaml \ - templates/cluster-template-flatcar.yaml + templates/cluster-template-flatcar.yaml \ + templates/cluster-template-flatcar-sysext.yaml -templates/cluster-template.yaml: kustomize/v1alpha7/default $(KUSTOMIZE) FORCE +templates/cluster-template.yaml: kustomize/v1beta1/default $(KUSTOMIZE) FORCE $(KUSTOMIZE) build "$<" > "$@" -templates/cluster-template-%.yaml: kustomize/v1alpha7/% $(KUSTOMIZE) FORCE +templates/cluster-template-%.yaml: kustomize/v1beta1/% $(KUSTOMIZE) FORCE $(KUSTOMIZE) build "$<" > "$@" .PHONY: release-templates diff --git a/OWNERS b/OWNERS index 8b5bf82409..ea64e2e7b8 100644 --- a/OWNERS +++ b/OWNERS @@ -19,3 +19,5 @@ emeritus_approvers: - sbueringer - hidekazuna - chrischdi + - tobiasgiese + - seanschneeweiss diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index c9a9af82e8..e4bda950ca 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -22,7 +22,6 @@ aliases: - jichenjc - lentzi90 - mdbooth - - seanschneeweiss - - tobiasgiese cluster-api-openstack-reviewers: + - emilienm - dulek diff --git a/PROJECT b/PROJECT index 6544f82880..6b397b884f 100644 --- a/PROJECT +++ b/PROJECT @@ -1,40 +1,59 @@ -version: "2" +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html domain: cluster.x-k8s.io repo: sigs.k8s.io/cluster-api-provider-openstack resources: - group: infrastructure - version: v1alpha5 kind: OpenStackCluster -- group: infrastructure version: v1alpha5 - kind: OpenStackMachine - group: infrastructure + kind: OpenStackMachine version: v1alpha5 +- group: infrastructure kind: OpenStackMachineTemplate + version: v1alpha5 - group: infrastructure kind: OpenStackClusterTemplate version: v1alpha5 - group: infrastructure - version: v1alpha6 kind: OpenStackCluster -- group: infrastructure version: v1alpha6 - kind: OpenStackMachine - group: infrastructure + kind: OpenStackMachine version: v1alpha6 +- group: infrastructure kind: OpenStackMachineTemplate + version: v1alpha6 - group: infrastructure kind: OpenStackClusterTemplate version: v1alpha6 - group: infrastructure - version: v1alpha7 kind: OpenStackCluster -- group: infrastructure version: v1alpha7 - kind: OpenStackMachine - group: infrastructure + kind: OpenStackMachine version: v1alpha7 +- group: infrastructure kind: OpenStackMachineTemplate + version: v1alpha7 - group: infrastructure kind: OpenStackClusterTemplate version: v1alpha7 +- group: infrastructure + version: v1beta1 + kind: OpenStackCluster +- group: infrastructure + version: v1beta1 + kind: OpenStackMachine +- group: infrastructure + version: v1beta1 + kind: OpenStackMachineTemplate +- group: infrastructure + kind: OpenStackClusterTemplate + version: v1beta1 +- group: infrastructure + kind: OpenStackFloatingIPPool + version: v1alpha1 +version: "2" diff --git a/README.md b/README.md index b683047e91..51b35911b5 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ This provider's versions are compatible with the following versions of Cluster A |------------------------------------| -------------- | | OpenStack Provider v1alpha5 (v0.6) | ✓ | | OpenStack Provider v1alpha6 (v0.7) | ✓ | -| OpenStack Provider v1alpha7 | ✓ | +| OpenStack Provider v1alpha7 (v0.9) | ✓ | +| OpenStack Provider v1beta1 | ✓ | This provider's versions are able to install and manage the following versions of Kubernetes: @@ -52,15 +53,17 @@ This provider's versions are able to install and manage the following versions o |------------------------------------| ----- | ----- | ----- | ----- | | OpenStack Provider v1alpha5 (v0.6) | ✓ | + | + | + | | OpenStack Provider v1alpha6 (v0.7) | ✓ | ✓ | ✓ | + | -| OpenStack Provider v1alpha7 | + | ✓ | ✓ | ★ | +| OpenStack Provider v1alpha7 (v0.9) | + | ✓ | ✓ | ★ | +| OpenStack Provider v1beta1 | + | ✓ | ✓ | ★ | This provider's versions are able to install Kubernetes to the following versions of OpenStack: -| | Queens | Rocky | Stein | Train | Ussuri | Victoria | Wallaby | Xena | Yoga | -|------------------------------------| ------ | ----- | ----- | ----- | ------ | -------- | ------- | ---- | ---- | -| OpenStack Provider v1alpha5 (v0.6) | + | + | + | + | + | ✓ | ✓ | ✓ | ★ | -| OpenStack Provider v1alpha6 (v0.7) | + | + | + | + | + | ✓ | ✓ | ✓ | ★ | -| OpenStack Provider v1alpha7 | | + | + | + | + | ✓ | ✓ | ✓ | ★ | +| | Queens | Rocky | Stein | Train | Ussuri | Victoria | Wallaby | Xena | Yoga | Bobcat | +|------------------------------------| ------ | ----- | ----- | ----- | ------ | -------- | ------- | ---- | ---- | ------ | +| OpenStack Provider v1alpha5 (v0.6) | + | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ | +| OpenStack Provider v1alpha6 (v0.7) | + | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ | +| OpenStack Provider v1alpha7 (v0.9) | | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ | +| OpenStack Provider v1beta1 | | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ | Test status: diff --git a/RELEASE.md b/RELEASE.md index 9f97d780ac..a86fd79693 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -60,11 +60,11 @@ The content of the release notes differs depending on the type of release, speci This will cause the image to be automatically built by CI and pushed to the staging repository. As this only builds the image, it only takes a few minutes. -1. Follow the [image promotion process](https://github.com/kubernetes/k8s.io/tree/main/k8s.gcr.io#image-promoter) to promote the image from the staging repo to `registry.k8s.io/capi-openstack`. +1. Follow the [image promotion process](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/README.md#image-promoter) to promote the image from the staging repo to `registry.k8s.io/capi-openstack`. The staging repository can be inspected at https://console.cloud.google.com/gcr/images/k8s-staging-capi-openstack/GLOBAL. Be sure to choose the top level `capi-openstack-controller`, which will provide the multi-arch manifest, rather than one for a specific architecture. The image build logs are available at [Cloud Build](https://console.cloud.google.com/cloud-build/builds?project=k8s-staging-capi-openstack). - Add the new sha=>tag mapping to the [images.yaml](https://github.com/kubernetes/k8s.io/edit/main/k8s.gcr.io/images/k8s-staging-capi-openstack/images.yaml) (use the sha of the image with the corresponding tag). The PR to update the [images.yaml](https://github.com/kubernetes/k8s.io/edit/main/k8s.gcr.io/images/k8s-staging-capi-openstack/images.yaml) must be approved in the [OWNERS](https://github.com/kubernetes/k8s.io/blob/main/k8s.gcr.io/images/k8s-staging-capi-openstack/OWNERS) file and merged. + Add the new sha=>tag mapping to the [images.yaml](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-capi-openstack/images.yaml) (use the sha of the image with the corresponding tag). The PR to update the [images.yaml](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-capi-openstack/images.yaml) must be approved in the [OWNERS](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-capi-openstack/OWNERS) file and merged. It is good practise to get somebody else to review this PR. It is safe to perform the following steps while waiting for review and the promotion of the image. @@ -92,12 +92,12 @@ The content of the release notes differs depending on the type of release, speci Releasing requires a particular set of permissions. -* Approver role for the image promoter process ([kubernetes/k8s.io/blob/main/k8s.gcr.io/images/k8s-staging-capi-openstack/OWNERS](https://github.com/kubernetes/k8s.io/blob/main/k8s.gcr.io/images/k8s-staging-capi-openstack/OWNERS)) +* Approver role for the image promoter process ([kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-capi-openstack/OWNERS](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-capi-openstack/OWNERS)) * Tag push and release creation rights to the GitHub repository (team `cluster-api-provider-openstack-maintainers` in [kubernetes/org/config/kubernetes-sigs/sig-cluster-lifecycle/teams.yaml](https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-cluster-lifecycle/teams.yaml)) ## Staging There is a post-submit Prow job running after each commit on `main` which pushes a new image to the staging repo (`gcr.io/k8s-staging-capi-openstack/capi-openstack-controller:latest`). Following configuration is involved: -* staging gcr bucket: [kubernetes/k8s.io/blob/main/k8s.gcr.io/manifests/k8s-staging-capi-openstack/promoter-manifest.yaml](https://github.com/kubernetes/k8s.io/blob/main/k8s.gcr.io/manifests/k8s-staging-capi-openstack/promoter-manifest.yaml) +* staging gcr bucket: [kubernetes/k8s.io/blob/main/registry.k8s.io/manifests/k8s-staging-capi-openstack/promoter-manifest.yaml](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/manifests/k8s-staging-capi-openstack/promoter-manifest.yaml) * post-submit `post-capi-openstack-push-images` Prow job: [kubernetes/test-infra/blob/master/config/jobs/image-pushing/k8s-staging-cluster-api.yaml](https://github.com/kubernetes/test-infra/blob/master/config/jobs/image-pushing/k8s-staging-cluster-api.yaml)) (corresponding dashboard is located at [https://testgrid.k8s.io/sig-cluster-lifecycle-image-pushes#post-capi-openstack-push-images](https://testgrid.k8s.io/sig-cluster-lifecycle-image-pushes#post-capi-openstack-push-images)) * Google Cloud Build configuration which is used by the Prow job: [kubernetes-sigs/cluster-api-provider-openstack/cloudbuild.yaml](https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/main/cloudbuild.yaml) diff --git a/api/v1alpha7/openstackclusterlist_webhook.go b/api/v1alpha1/conditions_consts.go similarity index 52% rename from api/v1alpha7/openstackclusterlist_webhook.go rename to api/v1alpha1/conditions_consts.go index f7749b7ade..e40c728ff8 100644 --- a/api/v1alpha7/openstackclusterlist_webhook.go +++ b/api/v1alpha1/conditions_consts.go @@ -14,19 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 +package v1alpha1 -import ( - "sigs.k8s.io/controller-runtime/pkg/builder" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/manager" -) +const ( + // OpenstackFloatingIPPoolReadyCondition reports on the current status of the floating ip pool. Ready indicates that the pool is ready to be used. + OpenstackFloatingIPPoolReadyCondition = "OpenstackFloatingIPPoolReadyCondition" -// log is for logging in this package. -var _ = logf.Log.WithName("openstackclusterlist-resource") + // MaxIPsReachedReason is set when the maximum number of floating IPs has been reached. + MaxIPsReachedReason = "MaxIPsReached" -func (r *OpenStackClusterList) SetupWebhookWithManager(mgr manager.Manager) error { - return builder.WebhookManagedBy(mgr). - For(r). - Complete() -} + // UnableToFindFloatingIPNetworkReason is used when the floating ip network is not found. + UnableToFindNetwork = "UnableToFindNetwork" +) diff --git a/api/v1alpha1/doc.go b/api/v1alpha1/doc.go new file mode 100644 index 0000000000..367506620a --- /dev/null +++ b/api/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// package v1alpha1 contains API Schema definitions for the infrastructure v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=infrastructure.cluster.x-k8s.io +package v1alpha1 diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/groupversion_info.go b/api/v1alpha1/groupversion_info.go similarity index 88% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/groupversion_info.go rename to api/v1alpha1/groupversion_info.go index 019caf4f0f..fee80edbaa 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/groupversion_info.go +++ b/api/v1alpha1/groupversion_info.go @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -// package v1alpha7 contains API Schema definitions for the infrastructure v1alpha7 API group +// package v1alpha1 contains API Schema definitions for the infrastructure v1alpha1 API group // +kubebuilder:object:generate=true // +groupName=infrastructure.cluster.x-k8s.io -package v1alpha7 +package v1alpha1 import ( "k8s.io/apimachinery/pkg/runtime/schema" @@ -26,7 +26,7 @@ import ( var ( // GroupVersion is group version used to register these objects. - GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha7"} + GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha1"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme. SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} diff --git a/api/v1alpha1/openstackfloatingippool_types.go b/api/v1alpha1/openstackfloatingippool_types.go new file mode 100644 index 0000000000..c3ecff3de1 --- /dev/null +++ b/api/v1alpha1/openstackfloatingippool_types.go @@ -0,0 +1,132 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" +) + +const ( + // OpenStackFloatingIPPoolFinalizer allows ReconcileOpenStackFloatingIPPool to clean up resources associated with OpenStackFloatingIPPool before + // removing it from the apiserver. + OpenStackFloatingIPPoolFinalizer = "openstackfloatingippool.infrastructure.cluster.x-k8s.io" + + OpenStackFloatingIPPoolNameIndex = "spec.poolRef.name" + + // OpenStackFloatingIPPoolIP. + DeleteFloatingIPFinalizer = "openstackfloatingippool.infrastructure.cluster.x-k8s.io/delete-floating-ip" +) + +// ReclaimPolicy is a string type alias to represent reclaim policies for floating ips. +type ReclaimPolicy string + +const ( + // ReclaimDelete is the reclaim policy for floating ips. + ReclaimDelete ReclaimPolicy = "Delete" + // ReclaimRetain is the reclaim policy for floating ips. + ReclaimRetain ReclaimPolicy = "Retain" +) + +// OpenStackFloatingIPPoolSpec defines the desired state of OpenStackFloatingIPPool. +type OpenStackFloatingIPPoolSpec struct { + // PreAllocatedFloatingIPs is a list of floating IPs precreated in OpenStack that should be used by this pool. + // These are used before allocating new ones and are not deleted from OpenStack when the pool is deleted. + PreAllocatedFloatingIPs []string `json:"preAllocatedFloatingIPs,omitempty"` + + // MaxIPs is the maximum number of floating ips that can be allocated from this pool, if nil there is no limit. + // If set, the pool will stop allocating floating ips when it reaches this number of ClaimedIPs. + // +optional + MaxIPs *int `json:"maxIPs,omitempty"` + + // IdentityRef is a reference to a identity to be used when reconciling this pool. + // +kubebuilder:validation:Required + IdentityRef infrav1.OpenStackIdentityReference `json:"identityRef"` + + // FloatingIPNetwork is the external network to use for floating ips, if there's only one external network it will be used by default + // +optional + FloatingIPNetwork *infrav1.NetworkParam `json:"floatingIPNetwork"` + + // The stratergy to use for reclaiming floating ips when they are released from a machine + // +kubebuilder:validation:Enum=Retain;Delete + ReclaimPolicy ReclaimPolicy `json:"reclaimPolicy"` +} + +// OpenStackFloatingIPPoolStatus defines the observed state of OpenStackFloatingIPPool. +type OpenStackFloatingIPPoolStatus struct { + // +kubebuilder:default={} + // +optional + ClaimedIPs []string `json:"claimedIPs"` + + // +kubebuilder:default={} + // +optional + AvailableIPs []string `json:"availableIPs"` + + // FailedIPs contains a list of floating ips that failed to be allocated + // +optional + FailedIPs []string `json:"failedIPs,omitempty"` + + // floatingIPNetwork contains information about the network used for floating ips + // +optional + FloatingIPNetwork *infrav1.NetworkStatus `json:"floatingIPNetwork,omitempty"` + + Conditions clusterv1.Conditions `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +// +kubebuilder:storageversion +//+kubebuilder:subresource:status + +// OpenStackFloatingIPPool is the Schema for the openstackfloatingippools API. +type OpenStackFloatingIPPool struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec OpenStackFloatingIPPoolSpec `json:"spec,omitempty"` + Status OpenStackFloatingIPPoolStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// OpenStackFloatingIPPoolList contains a list of OpenStackFloatingIPPool. +type OpenStackFloatingIPPoolList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []OpenStackFloatingIPPool `json:"items"` +} + +// GetConditions returns the observations of the operational state of the OpenStackFloatingIPPool resource. +func (r *OpenStackFloatingIPPool) GetConditions() clusterv1.Conditions { + return r.Status.Conditions +} + +// SetConditions sets the underlying service state of the OpenStackFloatingIPPool to the predescribed clusterv1.Conditions. +func (r *OpenStackFloatingIPPool) SetConditions(conditions clusterv1.Conditions) { + r.Status.Conditions = conditions +} + +func (r *OpenStackFloatingIPPool) GetFloatingIPTag() string { + return fmt.Sprintf("cluster-api-provider-openstack-fip-pool-%s", r.Name) +} + +func init() { + SchemeBuilder.Register(&OpenStackFloatingIPPool{}, &OpenStackFloatingIPPoolList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..113ac8664f --- /dev/null +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,159 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenStackFloatingIPPool) DeepCopyInto(out *OpenStackFloatingIPPool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackFloatingIPPool. +func (in *OpenStackFloatingIPPool) DeepCopy() *OpenStackFloatingIPPool { + if in == nil { + return nil + } + out := new(OpenStackFloatingIPPool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OpenStackFloatingIPPool) 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 *OpenStackFloatingIPPoolList) DeepCopyInto(out *OpenStackFloatingIPPoolList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackFloatingIPPool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackFloatingIPPoolList. +func (in *OpenStackFloatingIPPoolList) DeepCopy() *OpenStackFloatingIPPoolList { + if in == nil { + return nil + } + out := new(OpenStackFloatingIPPoolList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OpenStackFloatingIPPoolList) 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 *OpenStackFloatingIPPoolSpec) DeepCopyInto(out *OpenStackFloatingIPPoolSpec) { + *out = *in + if in.PreAllocatedFloatingIPs != nil { + in, out := &in.PreAllocatedFloatingIPs, &out.PreAllocatedFloatingIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.MaxIPs != nil { + in, out := &in.MaxIPs, &out.MaxIPs + *out = new(int) + **out = **in + } + out.IdentityRef = in.IdentityRef + if in.FloatingIPNetwork != nil { + in, out := &in.FloatingIPNetwork, &out.FloatingIPNetwork + *out = new(v1beta1.NetworkParam) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackFloatingIPPoolSpec. +func (in *OpenStackFloatingIPPoolSpec) DeepCopy() *OpenStackFloatingIPPoolSpec { + if in == nil { + return nil + } + out := new(OpenStackFloatingIPPoolSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenStackFloatingIPPoolStatus) DeepCopyInto(out *OpenStackFloatingIPPoolStatus) { + *out = *in + if in.ClaimedIPs != nil { + in, out := &in.ClaimedIPs, &out.ClaimedIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AvailableIPs != nil { + in, out := &in.AvailableIPs, &out.AvailableIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.FailedIPs != nil { + in, out := &in.FailedIPs, &out.FailedIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.FloatingIPNetwork != nil { + in, out := &in.FloatingIPNetwork, &out.FloatingIPNetwork + *out = new(v1beta1.NetworkStatus) + (*in).DeepCopyInto(*out) + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(apiv1beta1.Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackFloatingIPPoolStatus. +func (in *OpenStackFloatingIPPoolStatus) DeepCopy() *OpenStackFloatingIPPoolStatus { + if in == nil { + return nil + } + out := new(OpenStackFloatingIPPoolStatus) + in.DeepCopyInto(out) + return out +} diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go index 3f41962b92..c9d71031d1 100644 --- a/api/v1alpha5/conversion.go +++ b/api/v1alpha5/conversion.go @@ -17,13 +17,16 @@ limitations under the License. package v1alpha5 import ( + "errors" "strings" conversion "k8s.io/apimachinery/pkg/conversion" + "k8s.io/utils/ptr" utilconversion "sigs.k8s.io/cluster-api/util/conversion" ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversioncommon" ) var _ ctrlconversion.Convertible = &OpenStackCluster{} @@ -33,7 +36,7 @@ const trueString = "true" func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackCluster) - if err := Convert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(r, dst, nil); err != nil { + if err := Convert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(r, dst, nil); err != nil { return err } @@ -49,7 +52,7 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error { func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackCluster) - if err := Convert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(src, r, nil); err != nil { + if err := Convert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(src, r, nil); err != nil { return err } @@ -62,13 +65,13 @@ var _ ctrlconversion.Convertible = &OpenStackClusterList{} func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackClusterList) - return Convert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(r, dst, nil) + return Convert_v1alpha5_OpenStackClusterList_To_v1beta1_OpenStackClusterList(r, dst, nil) } func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackClusterList) - return Convert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(src, r, nil) + return Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(src, r, nil) } var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{} @@ -76,7 +79,7 @@ var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{} func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackClusterTemplate) - if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(r, dst, nil); err != nil { + if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(r, dst, nil); err != nil { return err } @@ -92,7 +95,7 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackClusterTemplate) - if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(src, r, nil); err != nil { + if err := Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(src, r, nil); err != nil { return err } @@ -100,12 +103,24 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error return utilconversion.MarshalData(src, r) } +var _ ctrlconversion.Convertible = &OpenStackClusterTemplateList{} + +func (r *OpenStackClusterTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterTemplateList) + return Convert_v1alpha5_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(r, dst, nil) +} + +func (r *OpenStackClusterTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterTemplateList) + return Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(src, r, nil) +} + var _ ctrlconversion.Convertible = &OpenStackMachine{} func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackMachine) - if err := Convert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine(r, dst, nil); err != nil { + if err := Convert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(r, dst, nil); err != nil { return err } @@ -121,7 +136,7 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error { func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackMachine) - if err := Convert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(src, r, nil); err != nil { + if err := Convert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(src, r, nil); err != nil { return err } @@ -134,13 +149,13 @@ var _ ctrlconversion.Convertible = &OpenStackMachineList{} func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackMachineList) - return Convert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(r, dst, nil) + return Convert_v1alpha5_OpenStackMachineList_To_v1beta1_OpenStackMachineList(r, dst, nil) } func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackMachineList) - return Convert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(src, r, nil) + return Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(src, r, nil) } var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{} @@ -148,7 +163,7 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{} func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackMachineTemplate) - if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(r, dst, nil); err != nil { + if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(r, dst, nil); err != nil { return err } @@ -164,7 +179,7 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackMachineTemplate) - if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(src, r, nil); err != nil { + if err := Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(src, r, nil); err != nil { return err } @@ -177,92 +192,291 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{} func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { dst := dstRaw.(*infrav1.OpenStackMachineTemplateList) - return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(r, dst, nil) + return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(r, dst, nil) } func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { src := srcRaw.(*infrav1.OpenStackMachineTemplateList) - return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(src, r, nil) + return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(src, r, nil) +} + +func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { + err := autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.ExternalNetwork != nil && in.ExternalNetwork.ID != nil { + out.ExternalNetworkID = *in.ExternalNetwork.ID + } + + if len(in.ManagedSubnets) > 0 { + out.NodeCIDR = in.ManagedSubnets[0].CIDR + out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers + } + + if in.Subnets != nil { + if len(in.Subnets) >= 1 { + if err := Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil { + return err + } + } + } + + if in.ManagedSecurityGroups != nil { + out.ManagedSecurityGroups = true + out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic + } + + if in.APIServerLoadBalancer != nil { + if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + return err + } + } + + out.CloudName = in.IdentityRef.CloudName + out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name} + + return nil } -func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { - // Our new flag has no equivalent in v1alpha5 - return autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s) +func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s conversion.Scope) error { + err := autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.ExternalNetworkID != "" { + out.ExternalNetwork = &infrav1.NetworkParam{ + ID: &in.ExternalNetworkID, + } + } + + emptySubnet := SubnetFilter{} + if in.Subnet != emptySubnet { + subnet := infrav1.SubnetParam{} + if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &subnet, s); err != nil { + return err + } + out.Subnets = []infrav1.SubnetParam{subnet} + } + + if len(in.NodeCIDR) > 0 { + out.ManagedSubnets = []infrav1.SubnetSpec{ + { + CIDR: in.NodeCIDR, + DNSNameservers: in.DNSNameservers, + }, + } + } + // We're dropping DNSNameservers even if these were set as without NodeCIDR it doesn't make sense. + + if in.ManagedSecurityGroups { + out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{} + if !in.AllowAllInClusterTraffic { + out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules() + } else { + out.ManagedSecurityGroups.AllowAllInClusterTraffic = true + } + } + + if in.APIServerLoadBalancer.Enabled { + out.APIServerLoadBalancer = &infrav1.APIServerLoadBalancer{} + if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, out.APIServerLoadBalancer, s); err != nil { + return err + } + } + + out.IdentityRef.CloudName = in.CloudName + if in.IdentityRef != nil { + out.IdentityRef.Name = in.IdentityRef.Name + } + + // The generated conversion function converts "" to &"" which is not what we want + if in.APIServerFloatingIP == "" { + out.APIServerFloatingIP = nil + } + if in.APIServerFixedIP == "" { + out.APIServerFixedIP = nil + } + + if in.APIServerPort != 0 { + out.APIServerPort = ptr.To(in.APIServerPort) + } + + return nil } -func Convert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in, out, s) +func Convert_v1beta1_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { + return autoConvert_v1beta1_LoadBalancer_To_v1alpha5_LoadBalancer(in, out, s) } -func Convert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *PortOpts, s conversion.Scope) error { - // value specs and propagate uplink status have been added in v1alpha7 but have no equivalent in v1alpha5 - err := autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in, out, s) +func Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *PortOpts, s conversion.Scope) error { + // value specs and propagate uplink status have been added in v1beta1 but have no equivalent in v1alpha5 + err := autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in, out, s) if err != nil { return err } - out.Profile = make(map[string]string) - if in.Profile.OVSHWOffload { - (out.Profile)["capabilities"] = "[\"switchdev\"]" + // The auto-generated function converts v1beta1 SecurityGroup to + // v1alpha6 SecurityGroup, but v1alpha6 SecurityGroupFilter is more + // appropriate. Unset them and convert to SecurityGroupFilter instead. + out.SecurityGroups = nil + if len(in.SecurityGroups) > 0 { + out.SecurityGroupFilters = make([]SecurityGroupParam, len(in.SecurityGroups)) + for i := range in.SecurityGroups { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { + return err + } + } } - if in.Profile.TrustedVF { - (out.Profile)["trusted"] = trueString + + if in.Profile != nil { + out.Profile = make(map[string]string) + if ptr.Deref(in.Profile.OVSHWOffload, false) { + (out.Profile)["capabilities"] = "[\"switchdev\"]" + } + if ptr.Deref(in.Profile.TrustedVF, false) { + (out.Profile)["trusted"] = trueString + } } + return nil } -func Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s) +func Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s conversion.Scope) error { + err := autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in, out, s) + if err != nil { + return err + } + + if in.ServerGroupID != "" { + out.ServerGroup = &infrav1.ServerGroupParam{ID: &in.ServerGroupID} + } + + imageParam := infrav1.ImageParam{} + if in.ImageUUID != "" { + imageParam.ID = &in.ImageUUID + } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both. + imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image} + } + out.Image = imageParam + + if in.IdentityRef != nil { + out.IdentityRef = &infrav1.OpenStackIdentityReference{Name: in.IdentityRef.Name} + } + if in.CloudName != "" { + if out.IdentityRef == nil { + out.IdentityRef = &infrav1.OpenStackIdentityReference{} + } + out.IdentityRef.CloudName = in.CloudName + } + + return nil } -func Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { - // Provider was originally added in v1alpha7, but was backported to v1alpha6, but has no equivalent in v1alpha5 - return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in, out, s) +func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { + // Provider was originally added in v1beta1, but was backported to v1alpha6, but has no equivalent in v1alpha5 + return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in, out, s) } -func Convert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.PortOpts, s conversion.Scope) error { - // SecurityGroups have been removed in v1alpha7. - err := autoConvert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in, out, s) +func Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.PortOpts, s conversion.Scope) error { + // SecurityGroups have been removed in v1beta1. + err := autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in, out, s) if err != nil { return err } - // Profile is now a struct in v1alpha7. + if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 { + out.SecurityGroups = make([]infrav1.SecurityGroupParam, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) + for i := range in.SecurityGroupFilters { + sgParam := &in.SecurityGroupFilters[i] + switch { + case sgParam.UUID != "": + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &sgParam.UUID}) + case sgParam.Name != "": + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{Filter: &infrav1.SecurityGroupFilter{Name: sgParam.Name}}) + case sgParam.Filter != (SecurityGroupFilter{}): + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{}) + outSG := &out.SecurityGroups[len(out.SecurityGroups)-1] + outSG.Filter = &infrav1.SecurityGroupFilter{} + if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG.Filter, s); err != nil { + return err + } + } + } + for i := range in.SecurityGroups { + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]}) + } + } + + if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 { + out.SecurityGroups = make([]infrav1.SecurityGroupParam, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) + for i := range in.SecurityGroupFilters { + sgParam := &in.SecurityGroupFilters[i] + switch { + case sgParam.UUID != "": + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &sgParam.UUID}) + case sgParam.Name != "": + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{Filter: &infrav1.SecurityGroupFilter{Name: sgParam.Name}}) + case sgParam.Filter != (SecurityGroupFilter{}): + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{}) + outSG := &out.SecurityGroups[len(out.SecurityGroups)-1] + outSG.Filter = &infrav1.SecurityGroupFilter{} + if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG.Filter, s); err != nil { + return err + } + } + } + for i := range in.SecurityGroups { + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]}) + } + } + + // Profile is now a struct in v1beta1. if strings.Contains(in.Profile["capabilities"], "switchdev") { - out.Profile.OVSHWOffload = true + out.Profile.OVSHWOffload = ptr.To(true) } if in.Profile["trusted"] == trueString { - out.Profile.TrustedVF = true + out.Profile.TrustedVF = ptr.To(true) } return nil } -func Convert_v1alpha5_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error { - // BastionStatus is the same as Instance with unused fields removed +func Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error { + // BastionStatus is the same as Spec with unused fields removed out.ID = in.ID out.Name = in.Name out.SSHKeyName = in.SSHKeyName out.State = infrav1.InstanceState(in.State) out.IP = in.IP out.FloatingIP = in.FloatingIP + + if out.Resolved == nil { + out.Resolved = &infrav1.ResolvedMachineSpec{} + } + out.Resolved.ServerGroupID = in.ServerGroupID return nil } -func Convert_v1alpha7_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error { - // BastionStatus is the same as Instance with unused fields removed +func Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error { + // BastionStatus is the same as Spec with unused fields removed out.ID = in.ID out.Name = in.Name out.SSHKeyName = in.SSHKeyName out.State = InstanceState(in.State) out.IP = in.IP out.FloatingIP = in.FloatingIP + if in.Resolved != nil { + out.ServerGroupID = in.Resolved.ServerGroupID + } return nil } -func Convert_v1alpha5_Network_To_v1alpha7_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s conversion.Scope) error { - // PortOpts has been removed in v1alpha7 - err := Convert_v1alpha5_Network_To_v1alpha7_NetworkStatus(in, &out.NetworkStatus, s) +func Convert_v1alpha5_Network_To_v1beta1_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s conversion.Scope) error { + // PortOpts has been removed in v1beta1 + err := Convert_v1alpha5_Network_To_v1beta1_NetworkStatus(in, &out.NetworkStatus, s) if err != nil { return err } @@ -273,9 +487,9 @@ func Convert_v1alpha5_Network_To_v1alpha7_NetworkStatusWithSubnets(in *Network, return nil } -func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha5_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s conversion.Scope) error { - // PortOpts has been removed in v1alpha7 - err := Convert_v1alpha7_NetworkStatus_To_v1alpha5_Network(&in.NetworkStatus, out, s) +func Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha5_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s conversion.Scope) error { + // PortOpts has been removed in v1beta1 + err := Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(&in.NetworkStatus, out, s) if err != nil { return err } @@ -287,7 +501,7 @@ func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha5_Network(in *infrav1.N return nil } -func Convert_v1alpha5_Network_To_v1alpha7_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ conversion.Scope) error { +func Convert_v1alpha5_Network_To_v1beta1_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ conversion.Scope) error { out.ID = in.ID out.Name = in.Name out.Tags = in.Tags @@ -295,7 +509,7 @@ func Convert_v1alpha5_Network_To_v1alpha7_NetworkStatus(in *Network, out *infrav return nil } -func Convert_v1alpha7_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatus, out *Network, _ conversion.Scope) error { +func Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatus, out *Network, _ conversion.Scope) error { out.ID = in.ID out.Name = in.Name out.Tags = in.Tags @@ -303,98 +517,125 @@ func Convert_v1alpha7_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatu return nil } -func Convert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s conversion.Scope) error { - err := autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s) - if err != nil { - return err +func Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *infrav1.SecurityGroupParam, s conversion.Scope) error { + if in.UUID != "" { + out.ID = &in.UUID + return nil } - // TenantID has been removed in v1alpha7. Write it to ProjectID if ProjectID is not already set. - if out.ProjectID == "" { - out.ProjectID = in.TenantID + outFilter := &infrav1.SecurityGroupFilter{} + if in.Name != "" { + outFilter.Name = in.Name + } else { + // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1 + err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, outFilter, s) + if err != nil { + return err + } } + if !outFilter.IsZero() { + out.Filter = outFilter + } return nil } -func Convert_v1alpha5_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha7 - err := Convert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.Filter, out, s) - if err != nil { - return err +func Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupParam, out *SecurityGroupParam, s conversion.Scope) error { + if in.ID != nil { + out.UUID = *in.ID + return nil } - if in.UUID != "" { - out.ID = in.UUID - } - if in.Name != "" { - out.Name = in.Name + if in.Filter != nil { + err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in.Filter, &out.Filter, s) + if err != nil { + return err + } } return nil } -func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s conversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha7 - err := Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, &out.Filter, s) - if err != nil { - return err +func Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetParam(in *SubnetParam, out *infrav1.SubnetParam, s conversion.Scope) error { + if in.UUID != "" { + out.ID = &in.UUID + return nil } - - if in.ID != "" { - out.UUID = in.ID + outFilter := &infrav1.SubnetFilter{} + if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, outFilter, s); err != nil { + return err } - if in.Name != "" { - out.Name = in.Name + if !outFilter.IsZero() { + out.Filter = outFilter } return nil } -func Convert_v1alpha5_SubnetParam_To_v1alpha7_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ conversion.Scope) error { - *out = infrav1.SubnetFilter(in.Filter) - if in.UUID != "" { - out.ID = in.UUID +func Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetParam(in *infrav1.SubnetParam, out *SubnetParam, s conversion.Scope) error { + if in.ID != nil { + out.UUID = *in.ID + return nil } + + if in.Filter != nil { + if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in.Filter, &out.Filter, s); err != nil { + return err + } + } + return nil } -func Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ conversion.Scope) error { - out.Filter = SubnetFilter(*in) - out.UUID = in.ID +func Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetParam(in *SubnetFilter, out *infrav1.SubnetParam, s conversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + out.Filter = &infrav1.SubnetFilter{} + return Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in, out.Filter, s) +} +func Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetFilter(in *infrav1.SubnetParam, out *SubnetFilter, s conversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + if in.Filter != nil { + return Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in.Filter, out, s) + } return nil } -func Convert_Map_string_To_Interface_To_v1alpha7_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ conversion.Scope) error { +func Convert_Map_string_To_Interface_To_v1beta1_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ conversion.Scope) error { for k, v := range in { if k == "capabilities" { if strings.Contains(v, "switchdev") { - out.OVSHWOffload = true + out.OVSHWOffload = ptr.To(true) } } if k == "trusted" && v == trueString { - out.TrustedVF = true + out.TrustedVF = ptr.To(true) } } return nil } -func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error { - if in.OVSHWOffload { +func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error { + if ptr.Deref(in.OVSHWOffload, false) { (out)["capabilities"] = "[\"switchdev\"]" } - if in.TrustedVF { + if ptr.Deref(in.TrustedVF, false) { (out)["trusted"] = trueString } return nil } -func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { - err := autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in, out, s) +func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { + err := autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in, out, s) if err != nil { return err } - // Router and APIServerLoadBalancer have been moved out of Network in v1alpha7 + // Router and APIServerLoadBalancer have been moved out of Network in v1beta1 if in.Router != nil || in.APIServerLoadBalancer != nil { if out.Network == nil { out.Network = &Network{} @@ -403,7 +644,7 @@ func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus( out.Network.Router = (*Router)(in.Router) if in.APIServerLoadBalancer != nil { out.Network.APIServerLoadBalancer = &LoadBalancer{} - err = Convert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in.APIServerLoadBalancer, out.Network.APIServerLoadBalancer, s) + err = Convert_v1beta1_LoadBalancer_To_v1alpha5_LoadBalancer(in.APIServerLoadBalancer, out.Network.APIServerLoadBalancer, s) if err != nil { return err } @@ -413,18 +654,18 @@ func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus( return nil } -func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s conversion.Scope) error { - err := autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s) +func Convert_v1alpha5_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s conversion.Scope) error { + err := autoConvert_v1alpha5_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in, out, s) if err != nil { return err } - // Router and APIServerLoadBalancer have been moved out of Network in v1alpha7 + // Router and APIServerLoadBalancer have been moved out of Network in v1beta1 if in.Network != nil { out.Router = (*infrav1.Router)(in.Network.Router) if in.Network.APIServerLoadBalancer != nil { out.APIServerLoadBalancer = &infrav1.LoadBalancer{} - err = Convert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer(in.Network.APIServerLoadBalancer, out.APIServerLoadBalancer, s) + err = Convert_v1alpha5_LoadBalancer_To_v1beta1_LoadBalancer(in.Network.APIServerLoadBalancer, out.APIServerLoadBalancer, s) if err != nil { return err } @@ -434,6 +675,170 @@ func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus( return nil } -func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s) +func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { + err := autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s) + if err != nil { + return err + } + + if in.ServerGroup != nil && in.ServerGroup.ID != nil { + out.ServerGroupID = *in.ServerGroup.ID + } + + if in.Image.ID != nil { + out.ImageUUID = *in.Image.ID + } else if in.Image.Filter != nil && in.Image.Filter.Name != nil { + out.Image = *in.Image.Filter.Name + } + + if in.IdentityRef != nil { + out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name} + out.CloudName = in.IdentityRef.CloudName + } + + return nil +} + +func Convert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { + // ReferencedResources have no equivalent in v1alpha5 + return autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s) +} + +func Convert_v1beta1_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Bastion, s conversion.Scope) error { + err := autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in, out, s) + if err != nil { + return err + } + if in.FloatingIP != nil { + out.Instance.FloatingIP = *in.FloatingIP + } + return nil +} + +func Convert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Bastion, s conversion.Scope) error { + err := autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in, out, s) + if err != nil { + return err + } + if in.Instance.FloatingIP != "" { + out.FloatingIP = &in.Instance.FloatingIP + } + return nil +} + +func Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s conversion.Scope) error { //nolint:revive + out.ID = in.ID + out.Name = in.Name + return nil +} + +func Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s conversion.Scope) error { //nolint:revive + out.ID = in.ID + out.Name = in.Name + return nil +} + +func Convert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in, out, s) +} + +func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *infrav1.OpenStackIdentityReference, out *OpenStackIdentityReference, _ conversion.Scope) error { + out.Name = in.Name + return nil +} + +func Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *infrav1.SubnetFilter, s conversion.Scope) error { + if err := autoConvert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags) + return nil +} + +func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *infrav1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { + if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + return nil +} + +func Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s conversion.Scope) error { + if err := autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags) + + // TenantID has been removed in v1beta1. Write it to ProjectID if ProjectID is not already set. + if out.ProjectID == "" { + out.ProjectID = in.TenantID + } + return nil +} + +func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { + if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + return nil +} + +func Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkParam(in *NetworkFilter, out *infrav1.NetworkParam, s conversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + outFilter := &infrav1.NetworkFilter{} + if err := autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in, outFilter, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &outFilter.FilterByNeutronTags) + if !outFilter.IsZero() { + out.Filter = outFilter + } + return nil +} + +func Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkFilter(in *infrav1.NetworkParam, out *NetworkFilter, s conversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + if in.Filter != nil { + if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + } + return nil +} + +func Convert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *infrav1.RootVolume, s conversion.Scope) error { + out.SizeGiB = in.Size + out.Type = in.VolumeType + return conversioncommon.Convert_string_To_Pointer_v1beta1_VolumeAvailabilityZone(&in.AvailabilityZone, &out.AvailabilityZone, s) +} + +func Convert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in *infrav1.RootVolume, out *RootVolume, s conversion.Scope) error { + out.Size = in.SizeGiB + out.VolumeType = in.Type + return conversioncommon.Convert_Pointer_v1beta1_VolumeAvailabilityZone_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s) +} + +// conversion-gen registers the following functions so we have to define them, but nothing should ever call them. +func Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(_ *NetworkFilter, _ *infrav1.NetworkFilter, _ conversion.Scope) error { + return errors.New("Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter should not be called") +} + +func Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(_ *infrav1.NetworkFilter, _ *NetworkFilter, _ conversion.Scope) error { + return errors.New("Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter should not be called") +} + +func Convert_v1alpha5_NetworkParam_To_v1beta1_NetworkParam(_ *NetworkParam, _ *infrav1.NetworkParam, _ conversion.Scope) error { + return errors.New("Convert_v1alpha6_NetworkParam_To_v1beta1_NetworkParam should not be called") +} + +func Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkParam(_ *infrav1.NetworkParam, _ *NetworkParam, _ conversion.Scope) error { + return errors.New("Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkParam should not be called") } diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go index a7bfef2841..f180d9744a 100644 --- a/api/v1alpha5/conversion_test.go +++ b/api/v1alpha5/conversion_test.go @@ -17,14 +17,20 @@ limitations under the License. package v1alpha5 import ( + "runtime/debug" "testing" "github.com/onsi/gomega" + "github.com/onsi/gomega/format" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers" ) func TestConvertFrom(t *testing.T) { @@ -40,37 +46,45 @@ func TestConvertFrom(t *testing.T) { want ctrlconversion.Convertible }{ { - name: "conversion must have conversion-data annotation", + name: "cluster conversion must have conversion-data annotation", spoke: &OpenStackCluster{}, hub: &infrav1.OpenStackCluster{ Spec: infrav1.OpenStackClusterSpec{}, }, want: &OpenStackCluster{ - Spec: OpenStackClusterSpec{}, + Spec: OpenStackClusterSpec{ + IdentityRef: &OpenStackIdentityReference{}, + }, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}},\"status\":{\"ready\":false}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}", }, }, }, }, { - name: "conversion must have conversion-data annotation", + name: "cluster template conversion must have conversion-data annotation", spoke: &OpenStackClusterTemplate{}, hub: &infrav1.OpenStackClusterTemplate{ Spec: infrav1.OpenStackClusterTemplateSpec{}, }, want: &OpenStackClusterTemplate{ - Spec: OpenStackClusterTemplateSpec{}, + Spec: OpenStackClusterTemplateSpec{ + Template: OpenStackClusterTemplateResource{ + Spec: OpenStackClusterSpec{ + IdentityRef: &OpenStackIdentityReference{}, + }, + }, + }, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}}}}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}", }, }, }, }, { - name: "conversion must have conversion-data annotation", + name: "machine conversion must have conversion-data annotation", spoke: &OpenStackMachine{}, hub: &infrav1.OpenStackMachine{ Spec: infrav1.OpenStackMachineSpec{}, @@ -79,13 +93,13 @@ func TestConvertFrom(t *testing.T) { Spec: OpenStackMachineSpec{}, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"cloudName\":\"\",\"flavor\":\"\"},\"status\":{\"ready\":false}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"flavor\":\"\",\"image\":{}},\"status\":{\"ready\":false}}", }, }, }, }, { - name: "conversion must have conversion-data annotation", + name: "machine template conversion must have conversion-data annotation", spoke: &OpenStackMachineTemplate{}, hub: &infrav1.OpenStackMachineTemplate{ Spec: infrav1.OpenStackMachineTemplateSpec{}, @@ -94,7 +108,7 @@ func TestConvertFrom(t *testing.T) { Spec: OpenStackMachineTemplateSpec{}, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"cloudName\":\"\",\"flavor\":\"\"}}}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"flavor\":\"\",\"image\":{}}}}}", }, }, }, @@ -109,3 +123,117 @@ func TestConvertFrom(t *testing.T) { }) } } + +func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t *testing.T) { + tests := []struct { + name string + in *OpenStackClusterSpec + expectedOut *infrav1.OpenStackClusterSpec + }{ + { + name: "empty", + in: &OpenStackClusterSpec{}, + expectedOut: &infrav1.OpenStackClusterSpec{}, + }, + { + name: "with managed security groups and not allow all in cluster traffic", + in: &OpenStackClusterSpec{ + ManagedSecurityGroups: true, + AllowAllInClusterTraffic: false, + }, + expectedOut: &infrav1.OpenStackClusterSpec{ + ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{ + AllNodesSecurityGroupRules: infrav1.LegacyCalicoSecurityGroupRules(), + }, + }, + }, + { + name: "with managed security groups and allow all in cluster traffic", + in: &OpenStackClusterSpec{ + ManagedSecurityGroups: true, + AllowAllInClusterTraffic: true, + }, + expectedOut: &infrav1.OpenStackClusterSpec{ + ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{ + AllowAllInClusterTraffic: true, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + out := &infrav1.OpenStackClusterSpec{} + err := Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in, out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(out).To(gomega.Equal(tt.expectedOut)) + }) + } +} + +type convertiblePointer[T any] interface { + ctrlconversion.Convertible + *T +} + +type hubPointer[T any] interface { + ctrlconversion.Hub + *T +} + +func test_ObjectConvert[SP convertiblePointer[S], HP hubPointer[H], S, H any](tb testing.TB) { + tb.Helper() + + fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} { + return testhelpers.InfraV1FuzzerFuncs() + } + f := utilconversion.GetFuzzer(scheme.Scheme, fuzzerFuncs) + g := gomega.NewWithT(tb) + + for i := 0; i < 10000; i++ { + var hub HP = new(H) + f.Fuzz(hub) + var spoke SP = new(S) + + func() { + defer func() { + if r := recover(); r != nil { + tb.Errorf("PANIC! Down-converting:\n%s\n%s", format.Object(hub, 1), debug.Stack()) + tb.FailNow() + } + }() + g.Expect(spoke.ConvertFrom(hub)).To(gomega.Succeed()) + }() + + spoke = new(S) + f.Fuzz(spoke) + hub = new(H) + + func() { + defer func() { + if r := recover(); r != nil { + tb.Errorf("PANIC! Up-converting:\n%s\n%s", format.Object(spoke, 1), debug.Stack()) + tb.FailNow() + } + }() + g.Expect(spoke.ConvertTo(hub)).To(gomega.Succeed()) + }() + } +} + +func Test_OpenStackClusterConvert(t *testing.T) { + test_ObjectConvert[*OpenStackCluster, *infrav1.OpenStackCluster](t) +} + +func Test_OpenStackClusterTemplate(t *testing.T) { + test_ObjectConvert[*OpenStackClusterTemplate, *infrav1.OpenStackClusterTemplate](t) +} + +func Test_OpenStackMachineConvert(t *testing.T) { + test_ObjectConvert[*OpenStackMachine, *infrav1.OpenStackMachine](t) +} + +func Test_OpenStackMachineTemplateConvert(t *testing.T) { + test_ObjectConvert[*OpenStackMachineTemplate, *infrav1.OpenStackMachineTemplate](t) +} diff --git a/api/v1alpha5/doc.go b/api/v1alpha5/doc.go index 3793105e75..4b0192a1be 100644 --- a/api/v1alpha5/doc.go +++ b/api/v1alpha5/doc.go @@ -14,5 +14,5 @@ See the License for the specific language governing permissions and limitations under the License. */ -// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7 +// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1 package v1alpha5 diff --git a/api/v1alpha5/filter_convert.go b/api/v1alpha5/filter_convert.go deleted file mode 100644 index ab89bdca75..0000000000 --- a/api/v1alpha5/filter_convert.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha5 - -import ( - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" -) - -func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts { - return subnets.ListOpts{ - Name: subnetFilter.Name, - Description: subnetFilter.Description, - ProjectID: subnetFilter.ProjectID, - IPVersion: subnetFilter.IPVersion, - GatewayIP: subnetFilter.GatewayIP, - CIDR: subnetFilter.CIDR, - IPv6AddressMode: subnetFilter.IPv6AddressMode, - IPv6RAMode: subnetFilter.IPv6RAMode, - ID: subnetFilter.ID, - Tags: subnetFilter.Tags, - TagsAny: subnetFilter.TagsAny, - NotTags: subnetFilter.NotTags, - NotTagsAny: subnetFilter.NotTagsAny, - } -} - -func (networkFilter NetworkFilter) ToListOpt() networks.ListOpts { - return networks.ListOpts{ - Name: networkFilter.Name, - Description: networkFilter.Description, - ProjectID: networkFilter.ProjectID, - ID: networkFilter.ID, - Tags: networkFilter.Tags, - TagsAny: networkFilter.TagsAny, - NotTags: networkFilter.NotTags, - NotTagsAny: networkFilter.NotTagsAny, - } -} diff --git a/api/v1alpha5/openstackcluster_types.go b/api/v1alpha5/openstackcluster_types.go index e11aa158f7..3bc26c8cd1 100644 --- a/api/v1alpha5/openstackcluster_types.go +++ b/api/v1alpha5/openstackcluster_types.go @@ -206,6 +206,7 @@ type OpenStackClusterStatus struct { } // +kubebuilder:object:root=true +// +kubebuilder:unservedversion // +kubebuilder:deprecatedversion:warning="The v1alpha5 version of OpenStackCluster has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackclusters,scope=Namespaced,categories=cluster-api,shortName=osc // +kubebuilder:subresource:status diff --git a/api/v1alpha5/openstackclustertemplate_types.go b/api/v1alpha5/openstackclustertemplate_types.go index 5b14ab35c1..6dc4ef8d2a 100644 --- a/api/v1alpha5/openstackclustertemplate_types.go +++ b/api/v1alpha5/openstackclustertemplate_types.go @@ -31,6 +31,7 @@ type OpenStackClusterTemplateSpec struct { } // +kubebuilder:object:root=true +// +kubebuilder:unservedversion // +kubebuilder:deprecatedversion:warning="The v1alpha5 version of OpenStackClusterTemplate has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct diff --git a/api/v1alpha5/openstackmachine_types.go b/api/v1alpha5/openstackmachine_types.go index 7a41c82147..56e0c6619a 100644 --- a/api/v1alpha5/openstackmachine_types.go +++ b/api/v1alpha5/openstackmachine_types.go @@ -135,6 +135,7 @@ type OpenStackMachineStatus struct { } // +kubebuilder:object:root=true +// +kubebuilder:unservedversion // +kubebuilder:deprecatedversion:warning="The v1alpha5 version of OpenStackMachine has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackmachines,scope=Namespaced,categories=cluster-api,shortName=osm // +kubebuilder:subresource:status diff --git a/api/v1alpha5/openstackmachinetemplate_types.go b/api/v1alpha5/openstackmachinetemplate_types.go index 220229ce4f..7bb5d89628 100644 --- a/api/v1alpha5/openstackmachinetemplate_types.go +++ b/api/v1alpha5/openstackmachinetemplate_types.go @@ -26,6 +26,7 @@ type OpenStackMachineTemplateSpec struct { } // +kubebuilder:object:root=true +// +kubebuilder:unservedversion // +kubebuilder:deprecatedversion:warning="The v1alpha5 version of OpenStackMachineTemplate has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackmachinetemplates,scope=Namespaced,categories=cluster-api,shortName=osmt diff --git a/api/v1alpha5/types.go b/api/v1alpha5/types.go index d7b2c9ba28..5c1a37ac7d 100644 --- a/api/v1alpha5/types.go +++ b/api/v1alpha5/types.go @@ -118,8 +118,10 @@ type PortOpts struct { TenantID string `json:"tenantId,omitempty"` ProjectID string `json:"projectId,omitempty"` // The uuids of the security groups to assign to the instance + // +k8s:conversion-gen=false SecurityGroups []string `json:"securityGroups,omitempty"` // The names, uuids, filters or any combination these of the security groups to assign to the instance + // +k8s:conversion-gen=false SecurityGroupFilters []SecurityGroupParam `json:"securityGroupFilters,omitempty"` AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"` // Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited. @@ -239,7 +241,7 @@ type LoadBalancer struct { type SecurityGroup struct { Name string `json:"name"` ID string `json:"id"` - Rules []SecurityGroupRule `json:"rules"` + Rules []SecurityGroupRule `json:"rules,omitempty"` } // SecurityGroupRule represent the basic information of the associated OpenStack @@ -273,8 +275,8 @@ func (r SecurityGroupRule) Equal(x SecurityGroupRule) bool { type InstanceState string var ( - // InstanceStateBuilding is the string representing an instance in a building state. - InstanceStateBuilding = InstanceState("BUILDING") + // InstanceStateBuild is the string representing an instance in a build state. + InstanceStateBuild = InstanceState("BUILD") // InstanceStateActive is the string representing an instance in an active state. InstanceStateActive = InstanceState("ACTIVE") @@ -290,6 +292,9 @@ var ( // InstanceStateDeleted is the string representing an instance in a deleted state. InstanceStateDeleted = InstanceState("DELETED") + + // InstanceStateUndefined is the string representing an undefined instance state. + InstanceStateUndefined = InstanceState("") ) // Bastion represents basic information about the bastion node. diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index 52681a9c65..a77967fb5a 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,11 +24,14 @@ package v1alpha5 import ( unsafe "unsafe" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" - v1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" - v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" + v1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6" + v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" + apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" errors "sigs.k8s.io/cluster-api/errors" ) @@ -39,498 +42,544 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { - if err := s.AddGeneratedConversionFunc((*APIServerLoadBalancer)(nil), (*v1alpha7.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha7.APIServerLoadBalancer), scope) + if err := s.AddGeneratedConversionFunc((*APIServerLoadBalancer)(nil), (*v1beta1.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1beta1.APIServerLoadBalancer), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1alpha7.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_AddressPair_To_v1alpha7_AddressPair(a.(*AddressPair), b.(*v1alpha7.AddressPair), scope) + if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1beta1.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_AddressPair_To_v1beta1_AddressPair(a.(*AddressPair), b.(*v1beta1.AddressPair), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_AddressPair_To_v1alpha5_AddressPair(a.(*v1alpha7.AddressPair), b.(*AddressPair), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(a.(*v1beta1.AddressPair), b.(*AddressPair), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha7.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_Bastion_To_v1alpha7_Bastion(a.(*Bastion), b.(*v1alpha7.Bastion), scope) + if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1beta1.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1beta1.ExternalRouterIPParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_Bastion_To_v1alpha5_Bastion(a.(*v1alpha7.Bastion), b.(*Bastion), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(a.(*v1beta1.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1alpha7.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha7.ExternalRouterIPParam), scope) + if err := s.AddGeneratedConversionFunc((*FixedIP)(nil), (*v1beta1.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP(a.(*FixedIP), b.(*v1beta1.FixedIP), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(a.(*v1alpha7.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_FixedIP_To_v1alpha5_FixedIP(a.(*v1beta1.FixedIP), b.(*FixedIP), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*FixedIP)(nil), (*v1alpha7.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_FixedIP_To_v1alpha7_FixedIP(a.(*FixedIP), b.(*v1alpha7.FixedIP), scope) + if err := s.AddGeneratedConversionFunc((*LoadBalancer)(nil), (*v1beta1.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_LoadBalancer_To_v1beta1_LoadBalancer(a.(*LoadBalancer), b.(*v1beta1.LoadBalancer), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_FixedIP_To_v1alpha5_FixedIP(a.(*v1alpha7.FixedIP), b.(*FixedIP), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1beta1.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(a.(*OpenStackCluster), b.(*v1beta1.OpenStackCluster), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*LoadBalancer)(nil), (*v1alpha7.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha7.LoadBalancer), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(a.(*v1beta1.OpenStackCluster), b.(*OpenStackCluster), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*NetworkFilter)(nil), (*v1alpha7.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha7.NetworkFilter), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterList)(nil), (*v1beta1.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterList_To_v1beta1_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1beta1.OpenStackClusterList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(a.(*v1alpha7.NetworkFilter), b.(*NetworkFilter), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(a.(*v1beta1.OpenStackClusterList), b.(*OpenStackClusterList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1alpha7.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha7.OpenStackCluster), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1beta1.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1beta1.OpenStackClusterTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(a.(*v1alpha7.OpenStackCluster), b.(*OpenStackCluster), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(a.(*v1beta1.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterList)(nil), (*v1alpha7.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha7.OpenStackClusterList), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateList)(nil), (*v1beta1.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1beta1.OpenStackClusterTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(a.(*v1alpha7.OpenStackClusterList), b.(*OpenStackClusterList), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(a.(*v1beta1.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha7.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha7.OpenStackClusterSpec), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateResource)(nil), (*v1beta1.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1beta1.OpenStackClusterTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1alpha7.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha7.OpenStackClusterTemplate), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(a.(*v1beta1.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(a.(*v1alpha7.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateSpec)(nil), (*v1beta1.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1beta1.OpenStackClusterTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateList)(nil), (*v1alpha7.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha7.OpenStackClusterTemplateList), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(a.(*v1beta1.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(a.(*v1alpha7.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1beta1.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(a.(*OpenStackMachine), b.(*v1beta1.OpenStackMachine), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateResource)(nil), (*v1alpha7.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha7.OpenStackClusterTemplateResource), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(a.(*v1beta1.OpenStackMachine), b.(*OpenStackMachine), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(a.(*v1alpha7.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1beta1.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineList_To_v1beta1_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1beta1.OpenStackMachineList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateSpec)(nil), (*v1alpha7.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha7.OpenStackClusterTemplateSpec), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(a.(*v1beta1.OpenStackMachineList), b.(*OpenStackMachineList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(a.(*v1alpha7.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1beta1.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1beta1.OpenStackMachineStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha7.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha7.OpenStackIdentityReference), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1beta1.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1beta1.OpenStackMachineTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(a.(*v1alpha7.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(a.(*v1beta1.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1alpha7.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha7.OpenStackMachine), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1beta1.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1beta1.OpenStackMachineTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(a.(*v1alpha7.OpenStackMachine), b.(*OpenStackMachine), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(a.(*v1beta1.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1alpha7.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha7.OpenStackMachineList), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1beta1.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1beta1.OpenStackMachineTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(a.(*v1alpha7.OpenStackMachineList), b.(*OpenStackMachineList), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(a.(*v1beta1.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1alpha7.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha7.OpenStackMachineStatus), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1beta1.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1beta1.OpenStackMachineTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(a.(*v1alpha7.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(a.(*v1beta1.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1alpha7.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha7.OpenStackMachineTemplate), scope) + if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1beta1.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_Router_To_v1beta1_Router(a.(*Router), b.(*v1beta1.Router), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(a.(*v1alpha7.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Router_To_v1alpha5_Router(a.(*v1beta1.Router), b.(*Router), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1alpha7.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha7.OpenStackMachineTemplateList), scope) + if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1beta1.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_Subnet_To_v1beta1_Subnet(a.(*Subnet), b.(*v1beta1.Subnet), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(a.(*v1alpha7.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Subnet_To_v1alpha5_Subnet(a.(*v1beta1.Subnet), b.(*Subnet), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1alpha7.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha7.OpenStackMachineTemplateResource), scope) + if err := s.AddConversionFunc((*Bastion)(nil), (*v1beta1.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_Bastion_To_v1beta1_Bastion(a.(*Bastion), b.(*v1beta1.Bastion), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(a.(*v1alpha7.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope) + if err := s.AddConversionFunc((*Instance)(nil), (*v1beta1.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(a.(*Instance), b.(*v1beta1.BastionStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1alpha7.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha7.OpenStackMachineTemplateSpec), scope) + if err := s.AddConversionFunc((*NetworkFilter)(nil), (*v1beta1.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(a.(*NetworkFilter), b.(*v1beta1.NetworkFilter), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(a.(*v1alpha7.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope) + if err := s.AddConversionFunc((*NetworkFilter)(nil), (*v1beta1.NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkParam(a.(*NetworkFilter), b.(*v1beta1.NetworkParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha7.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(a.(*RootVolume), b.(*v1alpha7.RootVolume), scope) + if err := s.AddConversionFunc((*NetworkParam)(nil), (*v1beta1.NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_NetworkParam_To_v1beta1_NetworkParam(a.(*NetworkParam), b.(*v1beta1.NetworkParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(a.(*v1alpha7.RootVolume), b.(*RootVolume), scope) + if err := s.AddConversionFunc((*Network)(nil), (*v1beta1.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_Network_To_v1beta1_NetworkStatus(a.(*Network), b.(*v1beta1.NetworkStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha7.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_Router_To_v1alpha7_Router(a.(*Router), b.(*v1alpha7.Router), scope) + if err := s.AddConversionFunc((*Network)(nil), (*v1beta1.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_Network_To_v1beta1_NetworkStatusWithSubnets(a.(*Network), b.(*v1beta1.NetworkStatusWithSubnets), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_Router_To_v1alpha5_Router(a.(*v1alpha7.Router), b.(*Router), scope) + if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1beta1.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1beta1.OpenStackClusterSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha7.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SecurityGroup_To_v1alpha7_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha7.SecurityGroup), scope) + if err := s.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1beta1.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1beta1.OpenStackClusterStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroup_To_v1alpha5_SecurityGroup(a.(*v1alpha7.SecurityGroup), b.(*SecurityGroup), scope) + if err := s.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1beta1.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1beta1.OpenStackIdentityReference), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(a.(*v1alpha7.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1beta1.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1beta1.OpenStackMachineSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha7.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha7.SecurityGroupRule), scope) + if err := s.AddConversionFunc((*PortOpts)(nil), (*v1beta1.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(a.(*PortOpts), b.(*v1beta1.PortOpts), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(a.(*v1alpha7.SecurityGroupRule), b.(*SecurityGroupRule), scope) + if err := s.AddConversionFunc((*RootVolume)(nil), (*v1beta1.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_RootVolume_To_v1beta1_RootVolume(a.(*RootVolume), b.(*v1beta1.RootVolume), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha7.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_Subnet_To_v1alpha7_Subnet(a.(*Subnet), b.(*v1alpha7.Subnet), scope) + if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1beta1.SecurityGroupFilter), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_Subnet_To_v1alpha5_Subnet(a.(*v1alpha7.Subnet), b.(*Subnet), scope) + if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*SubnetFilter)(nil), (*v1alpha7.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha7.SubnetFilter), scope) + if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1beta1.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1beta1.SecurityGroupStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(a.(*v1alpha7.SubnetFilter), b.(*SubnetFilter), scope) + if err := s.AddConversionFunc((*SubnetFilter)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(a.(*SubnetFilter), b.(*v1beta1.SubnetFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*Instance)(nil), (*v1alpha7.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_Instance_To_v1alpha7_BastionStatus(a.(*Instance), b.(*v1alpha7.BastionStatus), scope) + if err := s.AddConversionFunc((*SubnetFilter)(nil), (*v1beta1.SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetParam(a.(*SubnetFilter), b.(*v1beta1.SubnetParam), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*Network)(nil), (*v1alpha7.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_Network_To_v1alpha7_NetworkStatus(a.(*Network), b.(*v1alpha7.NetworkStatus), scope) + if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetParam(a.(*SubnetParam), b.(*v1beta1.SubnetParam), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*Network)(nil), (*v1alpha7.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_Network_To_v1alpha7_NetworkStatusWithSubnets(a.(*Network), b.(*v1alpha7.NetworkStatusWithSubnets), scope) + if err := s.AddConversionFunc((*v1beta1.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(a.(*v1beta1.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha7.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha7.OpenStackClusterStatus), scope) + if err := s.AddConversionFunc((*v1beta1.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(a.(*v1beta1.BastionStatus), b.(*Instance), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha7.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha7.OpenStackMachineSpec), scope) + if err := s.AddConversionFunc((*v1beta1.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Bastion_To_v1alpha5_Bastion(a.(*v1beta1.Bastion), b.(*Bastion), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*PortOpts)(nil), (*v1alpha7.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(a.(*PortOpts), b.(*v1alpha7.PortOpts), scope) + if err := s.AddConversionFunc((*v1beta1.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LoadBalancer_To_v1alpha5_LoadBalancer(a.(*v1beta1.LoadBalancer), b.(*LoadBalancer), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha7.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha7.SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(a.(*v1beta1.NetworkFilter), b.(*NetworkFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1alpha7.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1alpha7.SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkParam)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkFilter(a.(*v1beta1.NetworkParam), b.(*NetworkFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1alpha7.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SubnetParam_To_v1alpha7_SubnetFilter(a.(*SubnetParam), b.(*v1alpha7.SubnetFilter), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkParam)(nil), (*NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkParam(a.(*v1beta1.NetworkParam), b.(*NetworkParam), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(a.(*v1alpha7.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha5_Network(a.(*v1beta1.NetworkStatusWithSubnets), b.(*Network), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_BastionStatus_To_v1alpha5_Instance(a.(*v1alpha7.BastionStatus), b.(*Instance), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(a.(*v1beta1.NetworkStatus), b.(*Network), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(a.(*v1alpha7.LoadBalancer), b.(*LoadBalancer), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(a.(*v1beta1.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha5_Network(a.(*v1alpha7.NetworkStatusWithSubnets), b.(*Network), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(a.(*v1beta1.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_NetworkStatus_To_v1alpha5_Network(a.(*v1alpha7.NetworkStatus), b.(*Network), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(a.(*v1beta1.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(a.(*v1alpha7.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(a.(*v1beta1.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(a.(*v1alpha7.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(a.(*v1beta1.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(a.(*v1alpha7.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope) + if err := s.AddConversionFunc((*v1beta1.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(a.(*v1beta1.PortOpts), b.(*PortOpts), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(a.(*v1alpha7.PortOpts), b.(*PortOpts), scope) + if err := s.AddConversionFunc((*v1beta1.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RootVolume_To_v1alpha5_RootVolume(a.(*v1beta1.RootVolume), b.(*RootVolume), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1alpha7.SecurityGroupFilter), b.(*SecurityGroupParam), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1alpha7.SubnetFilter), b.(*SubnetParam), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(a.(*v1beta1.SecurityGroupParam), b.(*SecurityGroupParam), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(a.(*v1beta1.SecurityGroupStatus), b.(*SecurityGroup), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(a.(*v1beta1.SubnetFilter), b.(*SubnetFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetParam)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetFilter(a.(*v1beta1.SubnetParam), b.(*SubnetFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetParam)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetParam(a.(*v1beta1.SubnetParam), b.(*SubnetParam), scope) }); err != nil { return err } return nil } -func autoConvert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha7.APIServerLoadBalancer, s conversion.Scope) error { - out.Enabled = in.Enabled +func autoConvert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts)) out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) return nil } -// Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer is an autogenerated conversion function. -func Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha7.APIServerLoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s) +// Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer is an autogenerated conversion function. +func Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error { + return autoConvert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s) } -func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1alpha7.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { - out.Enabled = in.Enabled +func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts)) out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) // WARNING: in.Provider requires manual conversion: does not exist in peer-type + // WARNING: in.Network requires manual conversion: does not exist in peer-type + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha5_AddressPair_To_v1alpha7_AddressPair(in *AddressPair, out *v1alpha7.AddressPair, s conversion.Scope) error { +func autoConvert_v1alpha5_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error { out.IPAddress = in.IPAddress - out.MACAddress = in.MACAddress + if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha5_AddressPair_To_v1alpha7_AddressPair is an autogenerated conversion function. -func Convert_v1alpha5_AddressPair_To_v1alpha7_AddressPair(in *AddressPair, out *v1alpha7.AddressPair, s conversion.Scope) error { - return autoConvert_v1alpha5_AddressPair_To_v1alpha7_AddressPair(in, out, s) +// Convert_v1alpha5_AddressPair_To_v1beta1_AddressPair is an autogenerated conversion function. +func Convert_v1alpha5_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error { + return autoConvert_v1alpha5_AddressPair_To_v1beta1_AddressPair(in, out, s) } -func autoConvert_v1alpha7_AddressPair_To_v1alpha5_AddressPair(in *v1alpha7.AddressPair, out *AddressPair, s conversion.Scope) error { +func autoConvert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error { out.IPAddress = in.IPAddress - out.MACAddress = in.MACAddress + if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha7_AddressPair_To_v1alpha5_AddressPair is an autogenerated conversion function. -func Convert_v1alpha7_AddressPair_To_v1alpha5_AddressPair(in *v1alpha7.AddressPair, out *AddressPair, s conversion.Scope) error { - return autoConvert_v1alpha7_AddressPair_To_v1alpha5_AddressPair(in, out, s) +// Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair is an autogenerated conversion function. +func Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error { + return autoConvert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in, out, s) } -func autoConvert_v1alpha5_Bastion_To_v1alpha7_Bastion(in *Bastion, out *v1alpha7.Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled - if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil { +func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error { + if err := optional.Convert_bool_To_optional_Bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + // WARNING: in.Instance requires manual conversion: does not exist in peer-type + if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err } - out.AvailabilityZone = in.AvailabilityZone return nil } -// Convert_v1alpha5_Bastion_To_v1alpha7_Bastion is an autogenerated conversion function. -func Convert_v1alpha5_Bastion_To_v1alpha7_Bastion(in *Bastion, out *v1alpha7.Bastion, s conversion.Scope) error { - return autoConvert_v1alpha5_Bastion_To_v1alpha7_Bastion(in, out, s) -} - -func autoConvert_v1alpha7_Bastion_To_v1alpha5_Bastion(in *v1alpha7.Bastion, out *Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled - if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil { +func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error { + if err := optional.Convert_optional_Bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + // WARNING: in.Spec requires manual conversion: does not exist in peer-type + if err := optional.Convert_optional_String_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err } - out.AvailabilityZone = in.AvailabilityZone + // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_Bastion_To_v1alpha5_Bastion is an autogenerated conversion function. -func Convert_v1alpha7_Bastion_To_v1alpha5_Bastion(in *v1alpha7.Bastion, out *Bastion, s conversion.Scope) error { - return autoConvert_v1alpha7_Bastion_To_v1alpha5_Bastion(in, out, s) -} - -func autoConvert_v1alpha5_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha7.ExternalRouterIPParam, s conversion.Scope) error { +func autoConvert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1beta1.ExternalRouterIPParam, s conversion.Scope) error { out.FixedIP = in.FixedIP - if err := Convert_v1alpha5_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { + if err := Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { return err } return nil } -// Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam is an autogenerated conversion function. -func Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha7.ExternalRouterIPParam, s conversion.Scope) error { - return autoConvert_v1alpha5_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in, out, s) +// Convert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam is an autogenerated conversion function. +func Convert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1beta1.ExternalRouterIPParam, s conversion.Scope) error { + return autoConvert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in, out, s) } -func autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha7.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { +func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { out.FixedIP = in.FixedIP - if err := Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { + if err := Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { return err } return nil } -// Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam is an autogenerated conversion function. -func Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha7.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { - return autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in, out, s) +// Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam is an autogenerated conversion function. +func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { + return autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in, out, s) } -func autoConvert_v1alpha5_FixedIP_To_v1alpha7_FixedIP(in *FixedIP, out *v1alpha7.FixedIP, s conversion.Scope) error { - out.Subnet = (*v1alpha7.SubnetFilter)(unsafe.Pointer(in.Subnet)) - out.IPAddress = in.IPAddress +func autoConvert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error { + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(v1beta1.SubnetParam) + if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetParam(*in, *out, s); err != nil { + return err + } + } else { + out.Subnet = nil + } + if err := optional.Convert_string_To_optional_String(&in.IPAddress, &out.IPAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha5_FixedIP_To_v1alpha7_FixedIP is an autogenerated conversion function. -func Convert_v1alpha5_FixedIP_To_v1alpha7_FixedIP(in *FixedIP, out *v1alpha7.FixedIP, s conversion.Scope) error { - return autoConvert_v1alpha5_FixedIP_To_v1alpha7_FixedIP(in, out, s) +// Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP is an autogenerated conversion function. +func Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error { + return autoConvert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in, out, s) } -func autoConvert_v1alpha7_FixedIP_To_v1alpha5_FixedIP(in *v1alpha7.FixedIP, out *FixedIP, s conversion.Scope) error { - out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet)) - out.IPAddress = in.IPAddress +func autoConvert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error { + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(SubnetFilter) + if err := Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Subnet = nil + } + if err := optional.Convert_optional_String_To_string(&in.IPAddress, &out.IPAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha7_FixedIP_To_v1alpha5_FixedIP is an autogenerated conversion function. -func Convert_v1alpha7_FixedIP_To_v1alpha5_FixedIP(in *v1alpha7.FixedIP, out *FixedIP, s conversion.Scope) error { - return autoConvert_v1alpha7_FixedIP_To_v1alpha5_FixedIP(in, out, s) +// Convert_v1beta1_FixedIP_To_v1alpha5_FixedIP is an autogenerated conversion function. +func Convert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error { + return autoConvert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in, out, s) } -func autoConvert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer(in *LoadBalancer, out *v1alpha7.LoadBalancer, s conversion.Scope) error { +func autoConvert_v1alpha5_LoadBalancer_To_v1beta1_LoadBalancer(in *LoadBalancer, out *v1beta1.LoadBalancer, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.IP = in.IP @@ -539,94 +588,95 @@ func autoConvert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer(in *LoadBalancer return nil } -// Convert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer is an autogenerated conversion function. -func Convert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer(in *LoadBalancer, out *v1alpha7.LoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha5_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s) +// Convert_v1alpha5_LoadBalancer_To_v1beta1_LoadBalancer is an autogenerated conversion function. +func Convert_v1alpha5_LoadBalancer_To_v1beta1_LoadBalancer(in *LoadBalancer, out *v1beta1.LoadBalancer, s conversion.Scope) error { + return autoConvert_v1alpha5_LoadBalancer_To_v1beta1_LoadBalancer(in, out, s) } -func autoConvert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1alpha7.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { +func autoConvert_v1beta1_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.IP = in.IP out.InternalIP = in.InternalIP out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.LoadBalancerNetwork requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFilter, out *v1alpha7.NetworkFilter, s conversion.Scope) error { +func autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter is an autogenerated conversion function. -func Convert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFilter, out *v1alpha7.NetworkFilter, s conversion.Scope) error { - return autoConvert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s) -} - -func autoConvert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha7.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { +func autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha5_NetworkParam_To_v1beta1_NetworkParam(in *NetworkParam, out *v1beta1.NetworkParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.FixedIP requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.NetworkFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter) + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter is an autogenerated conversion function. -func Convert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha7.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { - return autoConvert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s) +func autoConvert_v1beta1_NetworkParam_To_v1alpha5_NetworkParam(in *v1beta1.NetworkParam, out *NetworkParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.NetworkFilter) + return nil } -func autoConvert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *OpenStackCluster, out *v1alpha7.OpenStackCluster, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1alpha5_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *OpenStackCluster, out *v1alpha7.OpenStackCluster, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(in, out, s) +// Convert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(in, out, s) } -func autoConvert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha7.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1beta1_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha7.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(in, out, s) +// Convert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster is an autogenerated conversion function. +func Convert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(in, out, s) } -func autoConvert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha7.OpenStackClusterList, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in *OpenStackClusterList, out *v1beta1.OpenStackClusterList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackCluster, len(*in)) + *out = make([]v1beta1.OpenStackCluster, len(*in)) for i := range *in { - if err := Convert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -636,18 +686,18 @@ func autoConvert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList( return nil } -// Convert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha7.OpenStackClusterList, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in, out, s) +// Convert_v1alpha5_OpenStackClusterList_To_v1beta1_OpenStackClusterList is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in *OpenStackClusterList, out *v1beta1.OpenStackClusterList, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha7.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1beta1.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackCluster, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -657,121 +707,122 @@ func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList( return nil } -// Convert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha7.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in, out, s) +// Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1beta1.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in, out, s) } -func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha7.OpenStackClusterSpec, s conversion.Scope) error { - out.CloudName = in.CloudName - out.NodeCIDR = in.NodeCIDR - if err := Convert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil { - return err - } - if err := Convert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } - out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) +func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error { + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type + // WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type + // WARNING: in.Network requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.NetworkFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam) + // WARNING: in.Subnet requires manual conversion: does not exist in peer-type + // WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs - *out = make([]v1alpha7.ExternalRouterIPParam, len(*in)) + *out = make([]v1beta1.ExternalRouterIPParam, len(*in)) for i := range *in { - if err := Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { out.ExternalRouterIPs = nil } - out.ExternalNetworkID = in.ExternalNetworkID - if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + // WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type + // WARNING: in.APIServerLoadBalancer requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.APIServerLoadBalancer vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.APIServerLoadBalancer) + if err := optional.Convert_bool_To_optional_Bool(&in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.APIServerFloatingIP, &out.APIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.APIServerFixedIP, &out.APIServerFixedIP, s); err != nil { + return err + } + if err := optional.Convert_int_To_optional_Int(&in.APIServerPort, &out.APIServerPort, s); err != nil { + return err + } + // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups) + // WARNING: in.AllowAllInClusterTraffic requires manual conversion: does not exist in peer-type + if err := optional.Convert_bool_To_optional_Bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil { return err } - out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP - out.APIServerFloatingIP = in.APIServerFloatingIP - out.APIServerFixedIP = in.APIServerFixedIP - out.APIServerPort = in.APIServerPort - out.ManagedSecurityGroups = in.ManagedSecurityGroups - out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic - out.DisablePortSecurity = in.DisablePortSecurity out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + // WARNING: in.ControlPlaneEndpoint requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint vs *sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint) out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones)) if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion - *out = new(v1alpha7.Bastion) - if err := Convert_v1alpha5_Bastion_To_v1alpha7_Bastion(*in, *out, s); err != nil { + *out = new(v1beta1.Bastion) + if err := Convert_v1alpha5_Bastion_To_v1beta1_Bastion(*in, *out, s); err != nil { return err } } else { out.Bastion = nil } - out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + // WARNING: in.IdentityRef requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.OpenStackIdentityReference vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference) return nil } -// Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha7.OpenStackClusterSpec, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s) -} - -func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha7.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { - out.CloudName = in.CloudName - out.NodeCIDR = in.NodeCIDR +func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { + // WARNING: in.ManagedSubnets requires manual conversion: does not exist in peer-type // WARNING: in.Router requires manual conversion: does not exist in peer-type - if err := Convert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil { - return err - } - if err := Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Network requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.NetworkFilter) + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type // WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type - out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs *out = make([]ExternalRouterIPParam, len(*in)) for i := range *in { - if err := Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { out.ExternalRouterIPs = nil } - out.ExternalNetworkID = in.ExternalNetworkID - if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + // WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type + // WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type + // WARNING: in.APIServerLoadBalancer requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.APIServerLoadBalancer vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.APIServerLoadBalancer) + if err := optional.Convert_optional_Bool_To_bool(&in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.APIServerFloatingIP, &out.APIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.APIServerFixedIP, &out.APIServerFixedIP, s); err != nil { + return err + } + if err := optional.Convert_optional_Int_To_int(&in.APIServerPort, &out.APIServerPort, s); err != nil { + return err + } + // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool) + if err := optional.Convert_optional_Bool_To_bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil { return err } - out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP - out.APIServerFloatingIP = in.APIServerFloatingIP - out.APIServerFixedIP = in.APIServerFixedIP - out.APIServerPort = in.APIServerPort - out.ManagedSecurityGroups = in.ManagedSecurityGroups - out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic - out.DisablePortSecurity = in.DisablePortSecurity out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + // WARNING: in.ControlPlaneEndpoint requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint vs sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint) out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones)) // WARNING: in.ControlPlaneOmitAvailabilityZone requires manual conversion: does not exist in peer-type if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion *out = new(Bastion) - if err := Convert_v1alpha7_Bastion_To_v1alpha5_Bastion(*in, *out, s); err != nil { + if err := Convert_v1beta1_Bastion_To_v1alpha5_Bastion(*in, *out, s); err != nil { return err } } else { out.Bastion = nil } - out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + // WARNING: in.IdentityRef requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.OpenStackIdentityReference) return nil } -func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha7.OpenStackClusterStatus, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1beta1.OpenStackClusterStatus, s conversion.Scope) error { out.Ready = in.Ready if in.Network != nil { in, out := &in.Network, &out.Network - *out = new(v1alpha7.NetworkStatusWithSubnets) - if err := Convert_v1alpha5_Network_To_v1alpha7_NetworkStatusWithSubnets(*in, *out, s); err != nil { + *out = new(v1beta1.NetworkStatusWithSubnets) + if err := Convert_v1alpha5_Network_To_v1beta1_NetworkStatusWithSubnets(*in, *out, s); err != nil { return err } } else { @@ -779,21 +830,45 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta } if in.ExternalNetwork != nil { in, out := &in.ExternalNetwork, &out.ExternalNetwork - *out = new(v1alpha7.NetworkStatus) - if err := Convert_v1alpha5_Network_To_v1alpha7_NetworkStatus(*in, *out, s); err != nil { + *out = new(v1beta1.NetworkStatus) + if err := Convert_v1alpha5_Network_To_v1beta1_NetworkStatus(*in, *out, s); err != nil { return err } } else { out.ExternalNetwork = nil } - out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) - out.ControlPlaneSecurityGroup = (*v1alpha7.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup)) - out.WorkerSecurityGroup = (*v1alpha7.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup)) - out.BastionSecurityGroup = (*v1alpha7.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup)) + out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) + if in.ControlPlaneSecurityGroup != nil { + in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.ControlPlaneSecurityGroup = nil + } + if in.WorkerSecurityGroup != nil { + in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.WorkerSecurityGroup = nil + } + if in.BastionSecurityGroup != nil { + in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.BastionSecurityGroup = nil + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion - *out = new(v1alpha7.BastionStatus) - if err := Convert_v1alpha5_Instance_To_v1alpha7_BastionStatus(*in, *out, s); err != nil { + *out = new(v1beta1.BastionStatus) + if err := Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(*in, *out, s); err != nil { return err } } else { @@ -804,12 +879,12 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta return nil } -func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *v1alpha7.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *v1beta1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { out.Ready = in.Ready if in.Network != nil { in, out := &in.Network, &out.Network *out = new(Network) - if err := Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha5_Network(*in, *out, s); err != nil { + if err := Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha5_Network(*in, *out, s); err != nil { return err } } else { @@ -818,7 +893,7 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta if in.ExternalNetwork != nil { in, out := &in.ExternalNetwork, &out.ExternalNetwork *out = new(Network) - if err := Convert_v1alpha7_NetworkStatus_To_v1alpha5_Network(*in, *out, s); err != nil { + if err := Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(*in, *out, s); err != nil { return err } } else { @@ -826,14 +901,38 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta } // WARNING: in.Router requires manual conversion: does not exist in peer-type // WARNING: in.APIServerLoadBalancer requires manual conversion: does not exist in peer-type - out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) - out.ControlPlaneSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup)) - out.WorkerSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup)) - out.BastionSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup)) + out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) + if in.ControlPlaneSecurityGroup != nil { + in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.ControlPlaneSecurityGroup = nil + } + if in.WorkerSecurityGroup != nil { + in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.WorkerSecurityGroup = nil + } + if in.BastionSecurityGroup != nil { + in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.BastionSecurityGroup = nil + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion *out = new(Instance) - if err := Convert_v1alpha7_BastionStatus_To_v1alpha5_Instance(*in, *out, s); err != nil { + if err := Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(*in, *out, s); err != nil { return err } } else { @@ -844,39 +943,39 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta return nil } -func autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha7.OpenStackClusterTemplate, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1beta1.OpenStackClusterTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha7.OpenStackClusterTemplate, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in, out, s) +// Convert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1beta1.OpenStackClusterTemplate, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha7.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha7.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in, out, s) } -func autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha7.OpenStackClusterTemplateList, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1beta1.OpenStackClusterTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackClusterTemplate, len(*in)) + *out = make([]v1beta1.OpenStackClusterTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -886,18 +985,18 @@ func autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClus return nil } -// Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha7.OpenStackClusterTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in, out, s) +// Convert_v1alpha5_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1beta1.OpenStackClusterTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha7.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1beta1.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackClusterTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -907,120 +1006,110 @@ func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClus return nil } -// Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha7.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1beta1.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in, out, s) } -func autoConvert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha7.OpenStackClusterTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1alpha5_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1beta1.OpenStackClusterTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha7.OpenStackClusterTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in, out, s) +// Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1beta1.OpenStackClusterTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1alpha7.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1beta1.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1alpha7.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1beta1.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in, out, s) } -func autoConvert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha7.OpenStackClusterTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1alpha5_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1beta1.OpenStackClusterTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha7.OpenStackClusterTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in, out, s) +// Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1beta1.OpenStackClusterTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1alpha7.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1beta1.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1alpha7.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1beta1.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in, out, s) } -func autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha7.OpenStackIdentityReference, s conversion.Scope) error { - out.Kind = in.Kind +func autoConvert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1beta1.OpenStackIdentityReference, s conversion.Scope) error { + // WARNING: in.Kind requires manual conversion: does not exist in peer-type out.Name = in.Name return nil } -// Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha7.OpenStackIdentityReference, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in, out, s) -} - -func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha7.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { - out.Kind = in.Kind +func autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { out.Name = in.Name + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha7.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in, out, s) -} - -func autoConvert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *OpenStackMachine, out *v1alpha7.OpenStackMachine, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *OpenStackMachine, out *v1alpha7.OpenStackMachine, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s) +// Convert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha7.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha7.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(in, out, s) +// Convert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(in, out, s) } -func autoConvert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha7.OpenStackMachineList, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackMachine, len(*in)) + *out = make([]v1beta1.OpenStackMachine, len(*in)) for i := range *in { - if err := Convert_v1alpha5_OpenStackMachine_To_v1alpha7_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1030,18 +1119,18 @@ func autoConvert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList( return nil } -// Convert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha7.OpenStackMachineList, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in, out, s) +// Convert_v1alpha5_OpenStackMachineList_To_v1beta1_OpenStackMachineList is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha7.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1beta1.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackMachine, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1051,25 +1140,25 @@ func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList( return nil } -// Convert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha7.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in, out, s) +// Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1beta1.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in, out, s) } -func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha7.OpenStackMachineSpec, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1beta1.OpenStackMachineSpec, s conversion.Scope) error { out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) - out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) - out.CloudName = in.CloudName + // WARNING: in.InstanceID requires manual conversion: does not exist in peer-type + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type out.Flavor = in.Flavor - out.Image = in.Image - out.ImageUUID = in.ImageUUID + // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam) + // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type out.SSHKeyName = in.SSHKeyName // WARNING: in.Networks requires manual conversion: does not exist in peer-type if in.Ports != nil { in, out := &in.Ports, &out.Ports - *out = make([]v1alpha7.PortOpts, len(*in)) + *out = make([]v1beta1.PortOpts, len(*in)) for i := range *in { - if err := Convert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1077,12 +1166,12 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec( out.Ports = nil } // WARNING: in.Subnet requires manual conversion: does not exist in peer-type - out.FloatingIP = in.FloatingIP + // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]v1alpha7.SecurityGroupFilter, len(*in)) + *out = make([]v1beta1.SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha5_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1091,39 +1180,51 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec( } out.Trunk = in.Trunk out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) + // WARNING: in.ServerMetadata requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*v1alpha7.RootVolume)(unsafe.Pointer(in.RootVolume)) - out.ServerGroupID = in.ServerGroupID - out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(v1beta1.RootVolume) + if err := Convert_v1alpha5_RootVolume_To_v1beta1_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } + // WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(v1beta1.OpenStackIdentityReference) + if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil { + return err + } + } else { + out.IdentityRef = nil + } return nil } -func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *v1alpha7.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *v1beta1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) - out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) - out.CloudName = in.CloudName out.Flavor = in.Flavor - out.Image = in.Image - out.ImageUUID = in.ImageUUID + // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam vs string) out.SSHKeyName = in.SSHKeyName if in.Ports != nil { in, out := &in.Ports, &out.Ports *out = make([]PortOpts, len(*in)) for i := range *in { - if err := Convert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { out.Ports = nil } - out.FloatingIP = in.FloatingIP if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1132,78 +1233,93 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec( } out.Trunk = in.Trunk out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) + // WARNING: in.ServerMetadata requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata vs map[string]string) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + if err := Convert_v1beta1_RootVolume_To_v1alpha5_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } // WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type - out.ServerGroupID = in.ServerGroupID - out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + // WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(OpenStackIdentityReference) + if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil { + return err + } + } else { + out.IdentityRef = nil + } + // WARNING: in.FloatingIPPoolRef requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha7.OpenStackMachineStatus, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1beta1.OpenStackMachineStatus, s conversion.Scope) error { out.Ready = in.Ready - out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) - out.InstanceState = (*v1alpha7.InstanceState)(unsafe.Pointer(in.InstanceState)) + out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.InstanceState = (*v1beta1.InstanceState)(unsafe.Pointer(in.InstanceState)) out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) - out.Conditions = *(*v1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) + out.Conditions = *(*apiv1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) return nil } -// Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha7.OpenStackMachineStatus, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s) +// Convert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1beta1.OpenStackMachineStatus, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha7.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1beta1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { out.Ready = in.Ready - out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + // WARNING: in.InstanceID requires manual conversion: does not exist in peer-type + out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses)) out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState)) + // WARNING: in.Resolved requires manual conversion: does not exist in peer-type + // WARNING: in.Resources requires manual conversion: does not exist in peer-type out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) - out.Conditions = *(*v1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) + out.Conditions = *(*apiv1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) return nil } -// Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha7.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s) -} - -func autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha7.OpenStackMachineTemplate, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1beta1.OpenStackMachineTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha7.OpenStackMachineTemplate, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in, out, s) +// Convert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1beta1.OpenStackMachineTemplate, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha7.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha7.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in, out, s) } -func autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha7.OpenStackMachineTemplateList, s conversion.Scope) error { +func autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1beta1.OpenStackMachineTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackMachineTemplate, len(*in)) + *out = make([]v1beta1.OpenStackMachineTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1213,18 +1329,18 @@ func autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMach return nil } -// Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha7.OpenStackMachineTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in, out, s) +// Convert_v1alpha5_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1beta1.OpenStackMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha7.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1beta1.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackMachineTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1234,145 +1350,160 @@ func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMach return nil } -// Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha7.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1beta1.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in, out, s) } -func autoConvert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha7.OpenStackMachineTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1alpha5_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1beta1.OpenStackMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha7.OpenStackMachineTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in, out, s) +// Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1beta1.OpenStackMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1alpha7.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1beta1.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1alpha7.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1beta1.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in, out, s) } -func autoConvert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha7.OpenStackMachineTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1alpha5_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1beta1.OpenStackMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha7.OpenStackMachineTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in, out, s) +// Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1beta1.OpenStackMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha5_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1alpha7.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1beta1.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1alpha7.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1beta1.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in, out, s) } -func autoConvert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *v1alpha7.PortOpts, s conversion.Scope) error { - out.Network = (*v1alpha7.NetworkFilter)(unsafe.Pointer(in.Network)) - out.NameSuffix = in.NameSuffix - out.Description = in.Description - out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp)) - out.MACAddress = in.MACAddress - out.FixedIPs = *(*[]v1alpha7.FixedIP)(unsafe.Pointer(&in.FixedIPs)) - // WARNING: in.TenantID requires manual conversion: does not exist in peer-type - // WARNING: in.ProjectID requires manual conversion: does not exist in peer-type - // WARNING: in.SecurityGroups requires manual conversion: does not exist in peer-type - if in.SecurityGroupFilters != nil { - in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters - *out = make([]v1alpha7.SecurityGroupFilter, len(*in)) +func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error { + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(v1beta1.NetworkParam) + if err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkParam(*in, *out, s); err != nil { + return err + } + } else { + out.Network = nil + } + if err := optional.Convert_string_To_optional_String(&in.NameSuffix, &out.NameSuffix, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.Description, &out.Description, s); err != nil { + return err + } + // WARNING: in.AdminStateUp requires manual conversion: does not exist in peer-type + // WARNING: in.MACAddress requires manual conversion: does not exist in peer-type + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]v1beta1.FixedIP, len(*in)) for i := range *in { - if err := Convert_v1alpha5_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { - out.SecurityGroupFilters = nil + out.FixedIPs = nil } - out.AllowedAddressPairs = *(*[]v1alpha7.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs)) + // WARNING: in.TenantID requires manual conversion: does not exist in peer-type + // WARNING: in.ProjectID requires manual conversion: does not exist in peer-type + // INFO: in.SecurityGroups opted out of conversion generation + // INFO: in.SecurityGroupFilters opted out of conversion generation + // WARNING: in.AllowedAddressPairs requires manual conversion: does not exist in peer-type out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) - out.HostID = in.HostID - out.VNICType = in.VNICType - // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile) - out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity)) + // WARNING: in.HostID requires manual conversion: does not exist in peer-type + // WARNING: in.VNICType requires manual conversion: does not exist in peer-type + // WARNING: in.Profile requires manual conversion: does not exist in peer-type + // WARNING: in.DisablePortSecurity requires manual conversion: does not exist in peer-type out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) return nil } -func autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *v1alpha7.PortOpts, out *PortOpts, s conversion.Scope) error { - out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network)) - out.NameSuffix = in.NameSuffix - out.Description = in.Description - out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp)) - out.MACAddress = in.MACAddress - out.FixedIPs = *(*[]FixedIP)(unsafe.Pointer(&in.FixedIPs)) - if in.SecurityGroupFilters != nil { - in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters - *out = make([]SecurityGroupParam, len(*in)) +func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error { + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkFilter) + if err := Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Network = nil + } + if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil { + return err + } + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]FixedIP, len(*in)) for i := range *in { - if err := Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_FixedIP_To_v1alpha5_FixedIP(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { - out.SecurityGroupFilters = nil + out.FixedIPs = nil + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]string, len(*in)) + for i := range *in { + if err := v1alpha6.Convert_v1beta1_SecurityGroupParam_To_string(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.SecurityGroups = nil } - out.AllowedAddressPairs = *(*[]AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs)) - out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) - out.HostID = in.HostID - out.VNICType = in.VNICType - // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile vs map[string]string) - out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity)) - // WARNING: in.PropagateUplinkStatus requires manual conversion: does not exist in peer-type out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - // WARNING: in.ValueSpecs requires manual conversion: does not exist in peer-type + out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) + // WARNING: in.ResolvedPortSpecFields requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error { - out.Size = in.Size - out.VolumeType = in.VolumeType - out.AvailabilityZone = in.AvailabilityZone +func autoConvert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error { + // WARNING: in.Size requires manual conversion: does not exist in peer-type + // WARNING: in.VolumeType requires manual conversion: does not exist in peer-type + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function. -func Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in, out, s) -} - -func autoConvert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { - out.Size = in.Size - out.VolumeType = in.VolumeType - out.AvailabilityZone = in.AvailabilityZone +func autoConvert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error { + // WARNING: in.SizeGiB requires manual conversion: does not exist in peer-type + // WARNING: in.BlockDeviceVolume requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume is an autogenerated conversion function. -func Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in, out, s) -} - -func autoConvert_v1alpha5_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Router, s conversion.Scope) error { +func autoConvert_v1alpha5_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) @@ -1380,12 +1511,12 @@ func autoConvert_v1alpha5_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Ro return nil } -// Convert_v1alpha5_Router_To_v1alpha7_Router is an autogenerated conversion function. -func Convert_v1alpha5_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Router, s conversion.Scope) error { - return autoConvert_v1alpha5_Router_To_v1alpha7_Router(in, out, s) +// Convert_v1alpha5_Router_To_v1beta1_Router is an autogenerated conversion function. +func Convert_v1alpha5_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error { + return autoConvert_v1alpha5_Router_To_v1beta1_Router(in, out, s) } -func autoConvert_v1alpha7_Router_To_v1alpha5_Router(in *v1alpha7.Router, out *Router, s conversion.Scope) error { +func autoConvert_v1beta1_Router_To_v1alpha5_Router(in *v1beta1.Router, out *Router, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) @@ -1393,37 +1524,13 @@ func autoConvert_v1alpha7_Router_To_v1alpha5_Router(in *v1alpha7.Router, out *Ro return nil } -// Convert_v1alpha7_Router_To_v1alpha5_Router is an autogenerated conversion function. -func Convert_v1alpha7_Router_To_v1alpha5_Router(in *v1alpha7.Router, out *Router, s conversion.Scope) error { - return autoConvert_v1alpha7_Router_To_v1alpha5_Router(in, out, s) +// Convert_v1beta1_Router_To_v1alpha5_Router is an autogenerated conversion function. +func Convert_v1beta1_Router_To_v1alpha5_Router(in *v1beta1.Router, out *Router, s conversion.Scope) error { + return autoConvert_v1beta1_Router_To_v1alpha5_Router(in, out, s) } -func autoConvert_v1alpha5_SecurityGroup_To_v1alpha7_SecurityGroup(in *SecurityGroup, out *v1alpha7.SecurityGroup, s conversion.Scope) error { - out.Name = in.Name - out.ID = in.ID - out.Rules = *(*[]v1alpha7.SecurityGroupRule)(unsafe.Pointer(&in.Rules)) - return nil -} - -// Convert_v1alpha5_SecurityGroup_To_v1alpha7_SecurityGroup is an autogenerated conversion function. -func Convert_v1alpha5_SecurityGroup_To_v1alpha7_SecurityGroup(in *SecurityGroup, out *v1alpha7.SecurityGroup, s conversion.Scope) error { - return autoConvert_v1alpha5_SecurityGroup_To_v1alpha7_SecurityGroup(in, out, s) -} - -func autoConvert_v1alpha7_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha7.SecurityGroup, out *SecurityGroup, s conversion.Scope) error { - out.Name = in.Name - out.ID = in.ID - out.Rules = *(*[]SecurityGroupRule)(unsafe.Pointer(&in.Rules)) - return nil -} - -// Convert_v1alpha7_SecurityGroup_To_v1alpha5_SecurityGroup is an autogenerated conversion function. -func Convert_v1alpha7_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha7.SecurityGroup, out *SecurityGroup, s conversion.Scope) error { - return autoConvert_v1alpha7_SecurityGroup_To_v1alpha5_SecurityGroup(in, out, s) -} - -func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha7.SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID +func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type out.Name = in.Name out.Description = in.Description // WARNING: in.TenantID requires manual conversion: does not exist in peer-type @@ -1432,69 +1539,35 @@ func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in // WARNING: in.Marker requires manual conversion: does not exist in peer-type // WARNING: in.SortKey requires manual conversion: does not exist in peer-type // WARNING: in.SortDir requires manual conversion: does not exist in peer-type - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha7.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID +func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter is an autogenerated conversion function. -func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha7.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - return autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s) -} - -func autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha7.SecurityGroupRule, s conversion.Scope) error { - out.Description = in.Description - out.ID = in.ID - out.Direction = in.Direction - out.EtherType = in.EtherType - out.SecurityGroupID = in.SecurityGroupID - out.PortRangeMin = in.PortRangeMin - out.PortRangeMax = in.PortRangeMax - out.Protocol = in.Protocol - out.RemoteGroupID = in.RemoteGroupID - out.RemoteIPPrefix = in.RemoteIPPrefix +func autoConvert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *v1beta1.SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.Name requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.SecurityGroupFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter) return nil } -// Convert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule is an autogenerated conversion function. -func Convert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha7.SecurityGroupRule, s conversion.Scope) error { - return autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in, out, s) -} - -func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha7.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error { - out.Description = in.Description - out.ID = in.ID - out.Direction = in.Direction - out.EtherType = in.EtherType - out.SecurityGroupID = in.SecurityGroupID - out.PortRangeMin = in.PortRangeMin - out.PortRangeMax = in.PortRangeMax - out.Protocol = in.Protocol - out.RemoteGroupID = in.RemoteGroupID - out.RemoteIPPrefix = in.RemoteIPPrefix +func autoConvert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(in *v1beta1.SecurityGroupParam, out *SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.SecurityGroupFilter) return nil } -// Convert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule is an autogenerated conversion function. -func Convert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha7.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error { - return autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in, out, s) -} - -func autoConvert_v1alpha5_Subnet_To_v1alpha7_Subnet(in *Subnet, out *v1alpha7.Subnet, s conversion.Scope) error { +func autoConvert_v1alpha5_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.CIDR = in.CIDR @@ -1502,12 +1575,12 @@ func autoConvert_v1alpha5_Subnet_To_v1alpha7_Subnet(in *Subnet, out *v1alpha7.Su return nil } -// Convert_v1alpha5_Subnet_To_v1alpha7_Subnet is an autogenerated conversion function. -func Convert_v1alpha5_Subnet_To_v1alpha7_Subnet(in *Subnet, out *v1alpha7.Subnet, s conversion.Scope) error { - return autoConvert_v1alpha5_Subnet_To_v1alpha7_Subnet(in, out, s) +// Convert_v1alpha5_Subnet_To_v1beta1_Subnet is an autogenerated conversion function. +func Convert_v1alpha5_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { + return autoConvert_v1alpha5_Subnet_To_v1beta1_Subnet(in, out, s) } -func autoConvert_v1alpha7_Subnet_To_v1alpha5_Subnet(in *v1alpha7.Subnet, out *Subnet, s conversion.Scope) error { +func autoConvert_v1beta1_Subnet_To_v1alpha5_Subnet(in *v1beta1.Subnet, out *Subnet, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.CIDR = in.CIDR @@ -1515,12 +1588,12 @@ func autoConvert_v1alpha7_Subnet_To_v1alpha5_Subnet(in *v1alpha7.Subnet, out *Su return nil } -// Convert_v1alpha7_Subnet_To_v1alpha5_Subnet is an autogenerated conversion function. -func Convert_v1alpha7_Subnet_To_v1alpha5_Subnet(in *v1alpha7.Subnet, out *Subnet, s conversion.Scope) error { - return autoConvert_v1alpha7_Subnet_To_v1alpha5_Subnet(in, out, s) +// Convert_v1beta1_Subnet_To_v1alpha5_Subnet is an autogenerated conversion function. +func Convert_v1beta1_Subnet_To_v1alpha5_Subnet(in *v1beta1.Subnet, out *Subnet, s conversion.Scope) error { + return autoConvert_v1beta1_Subnet_To_v1alpha5_Subnet(in, out, s) } -func autoConvert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter, out *v1alpha7.SubnetFilter, s conversion.Scope) error { +func autoConvert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1529,20 +1602,15 @@ func autoConvert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter out.CIDR = in.CIDR out.IPv6AddressMode = in.IPv6AddressMode out.IPv6RAMode = in.IPv6RAMode - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter is an autogenerated conversion function. -func Convert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter, out *v1alpha7.SubnetFilter, s conversion.Scope) error { - return autoConvert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s) -} - -func autoConvert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha7.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { +func autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1551,15 +1619,18 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha7.Sub out.CIDR = in.CIDR out.IPv6AddressMode = in.IPv6AddressMode out.IPv6RAMode = in.IPv6RAMode - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha5_SubnetParam_To_v1beta1_SubnetParam(in *SubnetParam, out *v1beta1.SubnetParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.SubnetFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SubnetFilter) return nil } -// Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter is an autogenerated conversion function. -func Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha7.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { - return autoConvert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(in, out, s) +func autoConvert_v1beta1_SubnetParam_To_v1alpha5_SubnetParam(in *v1beta1.SubnetParam, out *SubnetParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SubnetFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.SubnetFilter) + return nil } diff --git a/api/v1alpha5/zz_generated.deepcopy.go b/api/v1alpha5/zz_generated.deepcopy.go index 17bb66b3f0..5b2d856eed 100644 --- a/api/v1alpha5/zz_generated.deepcopy.go +++ b/api/v1alpha5/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go deleted file mode 100644 index ae8e343ea8..0000000000 --- a/api/v1alpha6/conversion.go +++ /dev/null @@ -1,661 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha6 - -import ( - "reflect" - "strings" - - apiconversion "k8s.io/apimachinery/pkg/conversion" - ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" - - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" - "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" -) - -const trueString = "true" - -func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) { - // Subnet is removed from v1alpha7 with no replacement, so can't be - // losslessly converted. Restore the previously stored value on down-conversion. - dst.Subnet = previous.Subnet - - // Strictly speaking this is lossy because we lose changes in - // down-conversion which were made to the up-converted object. However - // it isn't worth implementing this as the fields are immutable. - dst.Networks = previous.Networks - dst.Ports = previous.Ports - dst.SecurityGroups = previous.SecurityGroups -} - -func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) { - // PortOpts.SecurityGroups have been removed in v1alpha7 - // We restore the whole PortOpts/Networks since they are anyway immutable. - if previous.ExternalNetwork != nil { - dst.ExternalNetwork.PortOpts = previous.ExternalNetwork.PortOpts - } - if previous.Network != nil { - dst.Network = previous.Network - } - if previous.Bastion != nil && previous.Bastion.Networks != nil { - dst.Bastion.Networks = previous.Bastion.Networks - } -} - -func restorev1alpha7MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) { - // PropagateUplinkStatus has been added in v1alpha7. - // We restore the whole Ports since they are anyway immutable. - dst.Ports = previous.Ports - dst.AdditionalBlockDevices = previous.AdditionalBlockDevices -} - -func restorev1alpha7Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) { - if *previous != nil && *dst != nil { - restorev1alpha7MachineSpec(&(*previous).Instance, &(*dst).Instance) - } -} - -func restorev1alpha7ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) { - // It's (theoretically) possible in v1alpha7 to have Network nil but - // Router or APIServerLoadBalancer not nil. In hub-spoke-hub conversion this will - // result in Network being a pointer to an empty object. - if previous.Network == nil && dst.Network != nil && reflect.ValueOf(*dst.Network).IsZero() { - dst.Network = nil - } -} - -func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) { - for i := range previous.ExternalRouterIPs { - dstIP := &dst.ExternalRouterIPs[i] - previousIP := &previous.ExternalRouterIPs[i] - - // Subnet.Filter.ID was overwritten in up-conversion by Subnet.UUID - dstIP.Subnet.Filter.ID = previousIP.Subnet.Filter.ID - - // If Subnet.UUID was previously unset, we overwrote it with the value of Subnet.Filter.ID - // Don't unset it again if it doesn't have the previous value of Subnet.Filter.ID, because that means it was genuinely changed - if previousIP.Subnet.UUID == "" && dstIP.Subnet.UUID == previousIP.Subnet.Filter.ID { - dstIP.Subnet.UUID = "" - } - } - - prevBastion := previous.Bastion - dstBastion := dst.Bastion - if prevBastion != nil && dstBastion != nil { - restorev1alpha6MachineSpec(&prevBastion.Instance, &dstBastion.Instance) - } -} - -var _ ctrlconversion.Convertible = &OpenStackCluster{} - -var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{ - "spec": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterSpec]{ - GetField: func(c *OpenStackCluster) *OpenStackClusterSpec { - return &c.Spec - }, - RestoreField: restorev1alpha6ClusterSpec, - }, - "status": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterStatus]{ - GetField: func(c *OpenStackCluster) *OpenStackClusterStatus { - return &c.Status - }, - RestoreField: restorev1alpha6ClusterStatus, - }, -} - -var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{ - "router": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackCluster, *infrav1.RouterFilter]{ - GetField: func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter { - return &c.Spec.Router - }, - }, - "networkMtu": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackCluster, int]{ - GetField: func(c *infrav1.OpenStackCluster) *int { - return &c.Spec.NetworkMTU - }, - }, - "bastion": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, *infrav1.Bastion]{ - GetField: func(c *infrav1.OpenStackCluster) **infrav1.Bastion { - return &c.Spec.Bastion - }, - RestoreField: restorev1alpha7Bastion, - }, - "status": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, infrav1.OpenStackClusterStatus]{ - GetField: func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus { - return &c.Status - }, - RestoreField: restorev1alpha7ClusterStatus, - }, -} - -func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackCluster) - - compare := &OpenStackCluster{} - return conversion.ConvertAndRestore( - r, dst, compare, - Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster, - v1alpha6OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer, - ) -} - -func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackCluster) - - compare := &infrav1.OpenStackCluster{} - return conversion.ConvertAndRestore( - src, r, compare, - Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster, - v1alpha7OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer, - ) -} - -var _ ctrlconversion.Convertible = &OpenStackClusterList{} - -func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackClusterList) - - return Convert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(r, dst, nil) -} - -func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackClusterList) - - return Convert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(src, r, nil) -} - -var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{} - -var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{ - "spec": conversion.HashedFieldRestorer[*OpenStackClusterTemplate, OpenStackClusterSpec]{ - GetField: func(c *OpenStackClusterTemplate) *OpenStackClusterSpec { - return &c.Spec.Template.Spec - }, - RestoreField: restorev1alpha6ClusterSpec, - }, -} - -var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{ - "router": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackClusterTemplate, *infrav1.RouterFilter]{ - GetField: func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter { - return &c.Spec.Template.Spec.Router - }, - }, - "networkMtu": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackClusterTemplate, int]{ - GetField: func(c *infrav1.OpenStackClusterTemplate) *int { - return &c.Spec.Template.Spec.NetworkMTU - }, - }, - "bastion": conversion.HashedFieldRestorer[*infrav1.OpenStackClusterTemplate, *infrav1.Bastion]{ - GetField: func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion { - return &c.Spec.Template.Spec.Bastion - }, - RestoreField: restorev1alpha7Bastion, - }, -} - -func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackClusterTemplate) - - compare := &OpenStackClusterTemplate{} - return conversion.ConvertAndRestore( - r, dst, compare, - Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, - v1alpha6OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer, - ) -} - -func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackClusterTemplate) - - compare := &infrav1.OpenStackClusterTemplate{} - return conversion.ConvertAndRestore( - src, r, compare, - Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, - v1alpha7OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer, - ) -} - -var _ ctrlconversion.Convertible = &OpenStackMachine{} - -var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{ - "spec": conversion.HashedFieldRestorer[*OpenStackMachine, OpenStackMachineSpec]{ - GetField: func(c *OpenStackMachine) *OpenStackMachineSpec { - return &c.Spec - }, - FilterField: func(s *OpenStackMachineSpec) *OpenStackMachineSpec { - // Despite being spec fields, ProviderID and InstanceID - // are both set by the machine controller. If these are - // the only changes to the spec, we still want to - // restore the rest of the spec to its original state. - if s.ProviderID != nil || s.InstanceID != nil { - f := *s - f.ProviderID = nil - f.InstanceID = nil - return &f - } - return s - }, - RestoreField: restorev1alpha6MachineSpec, - }, -} - -var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{ - "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachine, infrav1.OpenStackMachineSpec]{ - GetField: func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec { - return &c.Spec - }, - RestoreField: restorev1alpha7MachineSpec, - }, -} - -func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackMachine) - - compare := &OpenStackMachine{} - return conversion.ConvertAndRestore( - r, dst, compare, - Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine, - v1alpha6OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer, - ) -} - -func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackMachine) - - compare := &infrav1.OpenStackMachine{} - return conversion.ConvertAndRestore( - src, r, compare, - Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine, - v1alpha7OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer, - ) -} - -var _ ctrlconversion.Convertible = &OpenStackMachineList{} - -func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackMachineList) - return Convert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(r, dst, nil) -} - -func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackMachineList) - return Convert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(src, r, nil) -} - -var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{} - -var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{ - "spec": conversion.HashedFieldRestorer[*OpenStackMachineTemplate, OpenStackMachineSpec]{ - GetField: func(c *OpenStackMachineTemplate) *OpenStackMachineSpec { - return &c.Spec.Template.Spec - }, - RestoreField: restorev1alpha6MachineSpec, - }, -} - -var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{ - "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachineTemplate, infrav1.OpenStackMachineSpec]{ - GetField: func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec { - return &c.Spec.Template.Spec - }, - RestoreField: restorev1alpha7MachineSpec, - }, -} - -func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackMachineTemplate) - - compare := &OpenStackMachineTemplate{} - return conversion.ConvertAndRestore( - r, dst, compare, - Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, - v1alpha6OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer, - ) -} - -func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackMachineTemplate) - - compare := &infrav1.OpenStackMachineTemplate{} - return conversion.ConvertAndRestore( - src, r, compare, - Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, - v1alpha7OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer, - ) -} - -var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{} - -func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { - dst := dstRaw.(*infrav1.OpenStackMachineTemplateList) - return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(r, dst, nil) -} - -func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { - src := srcRaw.(*infrav1.OpenStackMachineTemplateList) - return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(src, r, nil) -} - -func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error { - err := autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s) - if err != nil { - return err - } - - if len(in.Networks) > 0 { - ports := convertNetworksToPorts(in.Networks) - // Networks were previously created first, so need to come before ports - out.Ports = append(ports, out.Ports...) - } - return nil -} - -func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts { - var ports []infrav1.PortOpts - - for i := range networks { - network := networks[i] - - // This will remain null if the network is not specified in NetworkParam - var networkFilter *infrav1.NetworkFilter - - // In v1alpha6, if network.Filter resolved to multiple networks - // then we would add multiple ports. It is not possible to - // support this behaviour during k8s API conversion as it - // requires an OpenStack API call. A network filter returning - // multiple networks now becomes an error when we attempt to - // create the port. - switch { - case network.UUID != "": - networkFilter = &infrav1.NetworkFilter{ - ID: network.UUID, - } - case network.Filter != (NetworkFilter{}): - networkFilter = (*infrav1.NetworkFilter)(&network.Filter) - } - - // Note that network.FixedIP was unused in v1alpha6 so we also ignore it here. - - // In v1alpha6, specifying multiple subnets created multiple - // ports. We maintain this behaviour in conversion by adding - // multiple portOpts in this case. - // - // Also, similar to network.Filter above, if a subnet filter - // resolved to multiple subnets then we would add a port for - // each subnet. Again, it is not possible to support this - // behaviour during k8s API conversion as it requires an - // OpenStack API call. A subnet filter returning multiple - // subnets now becomes an error when we attempt to create the - // port. - if len(network.Subnets) == 0 { - // If the network has no explicit subnets then we create a single port with no subnets. - ports = append(ports, infrav1.PortOpts{Network: networkFilter}) - } else { - // If the network has explicit subnets then we create a separate port for each subnet. - for i := range network.Subnets { - subnet := network.Subnets[i] - if subnet.UUID != "" { - ports = append(ports, infrav1.PortOpts{ - Network: networkFilter, - FixedIPs: []infrav1.FixedIP{ - {Subnet: &infrav1.SubnetFilter{ID: subnet.UUID}}, - }, - }) - } else { - ports = append(ports, infrav1.PortOpts{ - Network: networkFilter, - FixedIPs: []infrav1.FixedIP{ - {Subnet: (*infrav1.SubnetFilter)(&subnet.Filter)}, - }, - }) - } - } - } - } - - return ports -} - -func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in, out, s) -} - -func Convert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error { - err := autoConvert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(in, out, s) - if err != nil { - return err - } - // SecurityGroups are removed in v1alpha7 without replacement. SecurityGroupFilters can be used instead. - for i := range in.SecurityGroups { - out.SecurityGroupFilters = append(out.SecurityGroupFilters, infrav1.SecurityGroupFilter{ID: in.SecurityGroups[i]}) - } - - // Profile is now a struct in v1alpha7. - if strings.Contains(in.Profile["capabilities"], "switchdev") { - out.Profile.OVSHWOffload = true - } - if in.Profile["trusted"] == trueString { - out.Profile.TrustedVF = true - } - return nil -} - -func Convert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error { - // value specs and propagate uplink status have been added in v1alpha7 but have no equivalent in v1alpha5 - err := autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in, out, s) - if err != nil { - return err - } - - out.Profile = make(map[string]string) - if in.Profile.OVSHWOffload { - (out.Profile)["capabilities"] = "[\"switchdev\"]" - } - if in.Profile.TrustedVF { - (out.Profile)["trusted"] = trueString - } - return nil -} - -func Convert_v1alpha6_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ apiconversion.Scope) error { - // BastionStatus is the same as Instance with unused fields removed - out.ID = in.ID - out.Name = in.Name - out.SSHKeyName = in.SSHKeyName - out.State = infrav1.InstanceState(in.State) - out.IP = in.IP - out.FloatingIP = in.FloatingIP - return nil -} - -func Convert_v1alpha7_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStatus, out *Instance, _ apiconversion.Scope) error { - // BastionStatus is the same as Instance with unused fields removed - out.ID = in.ID - out.Name = in.Name - out.SSHKeyName = in.SSHKeyName - out.State = InstanceState(in.State) - out.IP = in.IP - out.FloatingIP = in.FloatingIP - return nil -} - -func Convert_v1alpha6_Network_To_v1alpha7_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s apiconversion.Scope) error { - // PortOpts has been removed in v1alpha7 - err := Convert_v1alpha6_Network_To_v1alpha7_NetworkStatus(in, &out.NetworkStatus, s) - if err != nil { - return err - } - - if in.Subnet != nil { - out.Subnets = []infrav1.Subnet{infrav1.Subnet(*in.Subnet)} - } - return nil -} - -func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha6_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s apiconversion.Scope) error { - // PortOpts has been removed in v1alpha7 - err := Convert_v1alpha7_NetworkStatus_To_v1alpha6_Network(&in.NetworkStatus, out, s) - if err != nil { - return err - } - - // Can only down-convert a single subnet - if len(in.Subnets) > 0 { - out.Subnet = (*Subnet)(&in.Subnets[0]) - } - return nil -} - -func Convert_v1alpha6_Network_To_v1alpha7_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ apiconversion.Scope) error { - out.ID = in.ID - out.Name = in.Name - out.Tags = in.Tags - - return nil -} - -func Convert_v1alpha7_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatus, out *Network, _ apiconversion.Scope) error { - out.ID = in.ID - out.Name = in.Name - out.Tags = in.Tags - - return nil -} - -func Convert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error { - err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s) - if err != nil { - return err - } - - // TenantID has been removed in v1alpha7. Write it to ProjectID if ProjectID is not already set. - if out.ProjectID == "" { - out.ProjectID = in.TenantID - } - - return nil -} - -func Convert_v1alpha6_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha7 - err := Convert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.Filter, out, s) - if err != nil { - return err - } - - if in.UUID != "" { - out.ID = in.UUID - } - if in.Name != "" { - out.Name = in.Name - } - return nil -} - -func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha7 - err := Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, &out.Filter, s) - if err != nil { - return err - } - - if in.ID != "" { - out.UUID = in.ID - } - if in.Name != "" { - out.Name = in.Name - } - return nil -} - -func Convert_v1alpha6_SubnetParam_To_v1alpha7_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ apiconversion.Scope) error { - *out = infrav1.SubnetFilter(in.Filter) - if in.UUID != "" { - out.ID = in.UUID - } - return nil -} - -func Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ apiconversion.Scope) error { - out.Filter = SubnetFilter(*in) - out.UUID = in.ID - - return nil -} - -func Convert_Map_string_To_Interface_To_v1alpha7_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ apiconversion.Scope) error { - for k, v := range in { - if k == "capabilities" { - if strings.Contains(v, "switchdev") { - out.OVSHWOffload = true - } - } - if k == "trusted" && v == trueString { - out.TrustedVF = true - } - } - return nil -} - -func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error { - if in.OVSHWOffload { - (out)["capabilities"] = "[\"switchdev\"]" - } - if in.TrustedVF { - (out)["trusted"] = trueString - } - return nil -} - -func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error { - err := autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in, out, s) - if err != nil { - return err - } - - // Router and APIServerLoadBalancer have been moved out of Network in v1alpha7 - if in.Router != nil || in.APIServerLoadBalancer != nil { - if out.Network == nil { - out.Network = &Network{} - } - - out.Network.Router = (*Router)(in.Router) - out.Network.APIServerLoadBalancer = (*LoadBalancer)(in.APIServerLoadBalancer) - } - - return nil -} - -func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s apiconversion.Scope) error { - err := autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s) - if err != nil { - return err - } - - // Router and APIServerLoadBalancer have been moved out of Network in v1alpha7 - if in.Network != nil { - out.Router = (*infrav1.Router)(in.Network.Router) - out.APIServerLoadBalancer = (*infrav1.LoadBalancer)(in.Network.APIServerLoadBalancer) - } - - return nil -} - -func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s) -} diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go index a89815b285..106cc7aeab 100644 --- a/api/v1alpha6/conversion_test.go +++ b/api/v1alpha6/conversion_test.go @@ -19,17 +19,19 @@ package v1alpha6 import ( "testing" + "github.com/google/go-cmp/cmp" fuzz "github.com/google/gofuzz" "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" utilconversion "sigs.k8s.io/cluster-api/util/conversion" "sigs.k8s.io/controller-runtime/pkg/conversion" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/internal/futures" testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers" ) @@ -56,7 +58,7 @@ func TestFuzzyConversion(t *testing.T) { } fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} { - return []interface{}{ + v1alpha6FuzzerFuncs := []interface{}{ func(instance *Instance, c fuzz.Continue) { c.FuzzNoCustom(instance) @@ -88,7 +90,40 @@ func TestFuzzyConversion(t *testing.T) { status.ExternalNetwork.APIServerLoadBalancer = nil } }, + + func(spec *OpenStackMachineSpec, c fuzz.Continue) { + c.FuzzNoCustom(spec) + + // RandString() generates strings up to 20 + // characters long. To exercise truncation of + // long server metadata keys and values we need + // the possibility of strings > 255 chars. + genLongString := func() string { + var ret string + for len(ret) < 255 { + ret += c.RandString() + } + return ret + } + + // Existing server metadata keys will be short. Add a random number of long ones. + for c.RandBool() { + if spec.ServerMetadata == nil { + spec.ServerMetadata = map[string]string{} + } + spec.ServerMetadata[genLongString()] = c.RandString() + } + + // Randomly make some server metadata values long. + for k := range spec.ServerMetadata { + if c.RandBool() { + spec.ServerMetadata[k] = genLongString() + } + } + }, } + + return futures.SlicesConcat(v1alpha6FuzzerFuncs, testhelpers.InfraV1FuzzerFuncs()) } t.Run("for OpenStackCluster", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ @@ -112,6 +147,7 @@ func TestFuzzyConversion(t *testing.T) { Hub: &infrav1.OpenStackClusterTemplate{}, Spoke: &OpenStackClusterTemplate{}, HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }))) t.Run("for OpenStackClusterTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ @@ -119,13 +155,16 @@ func TestFuzzyConversion(t *testing.T) { Hub: &infrav1.OpenStackClusterTemplate{}, Spoke: &OpenStackClusterTemplate{}, HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }))) t.Run("for OpenStackMachine", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ Hub: &infrav1.OpenStackMachine{}, Spoke: &OpenStackMachine{}, HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }))) t.Run("for OpenStackMachine with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ @@ -133,13 +172,16 @@ func TestFuzzyConversion(t *testing.T) { Hub: &infrav1.OpenStackMachine{}, Spoke: &OpenStackMachine{}, HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }))) t.Run("for OpenStackMachineTemplate", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ Hub: &infrav1.OpenStackMachineTemplate{}, Spoke: &OpenStackMachineTemplate{}, HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }))) t.Run("for OpenStackMachineTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ @@ -147,7 +189,9 @@ func TestFuzzyConversion(t *testing.T) { Hub: &infrav1.OpenStackMachineTemplate{}, Spoke: &OpenStackMachineTemplate{}, HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, }))) } @@ -176,8 +220,8 @@ func TestNetworksToPorts(t *testing.T) { afterMachineSpec: infrav1.OpenStackMachineSpec{ Ports: []infrav1.PortOpts{ { - Network: &infrav1.NetworkFilter{ - ID: networkuuid, + Network: &infrav1.NetworkParam{ + ID: ptr.To(networkuuid), }, }, }, @@ -203,14 +247,18 @@ func TestNetworksToPorts(t *testing.T) { afterMachineSpec: infrav1.OpenStackMachineSpec{ Ports: []infrav1.PortOpts{ { - Network: &infrav1.NetworkFilter{ - Name: "network-name", - Description: "network-description", - ProjectID: "project-id", - Tags: "tags", - TagsAny: "tags-any", - NotTags: "not-tags", - NotTagsAny: "not-tags-any", + Network: &infrav1.NetworkParam{ + Filter: &infrav1.NetworkFilter{ + Name: "network-name", + Description: "network-description", + ProjectID: "project-id", + FilterByNeutronTags: infrav1.FilterByNeutronTags{ + Tags: []infrav1.NeutronTag{"tags"}, + TagsAny: []infrav1.NeutronTag{"tags-any"}, + NotTags: []infrav1.NeutronTag{"not-tags"}, + NotTagsAny: []infrav1.NeutronTag{"not-tags-any"}, + }, + }, }, }, }, @@ -233,13 +281,13 @@ func TestNetworksToPorts(t *testing.T) { afterMachineSpec: infrav1.OpenStackMachineSpec{ Ports: []infrav1.PortOpts{ { - Network: &infrav1.NetworkFilter{ - ID: networkuuid, + Network: &infrav1.NetworkParam{ + ID: ptr.To(networkuuid), }, FixedIPs: []infrav1.FixedIP{ { - Subnet: &infrav1.SubnetFilter{ - ID: subnetuuid, + Subnet: &infrav1.SubnetParam{ + ID: ptr.To(subnetuuid), }, }, }, @@ -277,24 +325,28 @@ func TestNetworksToPorts(t *testing.T) { afterMachineSpec: infrav1.OpenStackMachineSpec{ Ports: []infrav1.PortOpts{ { - Network: &infrav1.NetworkFilter{ - ID: networkuuid, + Network: &infrav1.NetworkParam{ + ID: ptr.To(networkuuid), }, FixedIPs: []infrav1.FixedIP{ { - Subnet: &infrav1.SubnetFilter{ - Name: "subnet-name", - Description: "subnet-description", - ProjectID: "project-id", - IPVersion: 6, - GatewayIP: "x.x.x.x", - CIDR: "y.y.y.y", - IPv6AddressMode: "address-mode", - IPv6RAMode: "ra-mode", - Tags: "tags", - TagsAny: "tags-any", - NotTags: "not-tags", - NotTagsAny: "not-tags-any", + Subnet: &infrav1.SubnetParam{ + Filter: &infrav1.SubnetFilter{ + Name: "subnet-name", + Description: "subnet-description", + ProjectID: "project-id", + IPVersion: 6, + GatewayIP: "x.x.x.x", + CIDR: "y.y.y.y", + IPv6AddressMode: "address-mode", + IPv6RAMode: "ra-mode", + FilterByNeutronTags: infrav1.FilterByNeutronTags{ + Tags: []infrav1.NeutronTag{"tags"}, + TagsAny: []infrav1.NeutronTag{"tags-any"}, + NotTags: []infrav1.NeutronTag{"not-tags"}, + NotTagsAny: []infrav1.NeutronTag{"not-tags-any"}, + }, + }, }, }, }, @@ -335,36 +387,40 @@ func TestNetworksToPorts(t *testing.T) { afterMachineSpec: infrav1.OpenStackMachineSpec{ Ports: []infrav1.PortOpts{ { - Network: &infrav1.NetworkFilter{ - ID: networkuuid, + Network: &infrav1.NetworkParam{ + ID: ptr.To(networkuuid), }, FixedIPs: []infrav1.FixedIP{ { - Subnet: &infrav1.SubnetFilter{ - ID: subnetuuid, + Subnet: &infrav1.SubnetParam{ + ID: ptr.To(subnetuuid), }, }, }, }, { - Network: &infrav1.NetworkFilter{ - ID: networkuuid, + Network: &infrav1.NetworkParam{ + ID: ptr.To(networkuuid), }, FixedIPs: []infrav1.FixedIP{ { - Subnet: &infrav1.SubnetFilter{ - Name: "subnet-name", - Description: "subnet-description", - ProjectID: "project-id", - IPVersion: 6, - GatewayIP: "x.x.x.x", - CIDR: "y.y.y.y", - IPv6AddressMode: "address-mode", - IPv6RAMode: "ra-mode", - Tags: "tags", - TagsAny: "tags-any", - NotTags: "not-tags", - NotTagsAny: "not-tags-any", + Subnet: &infrav1.SubnetParam{ + Filter: &infrav1.SubnetFilter{ + Name: "subnet-name", + Description: "subnet-description", + ProjectID: "project-id", + IPVersion: 6, + GatewayIP: "x.x.x.x", + CIDR: "y.y.y.y", + IPv6AddressMode: "address-mode", + IPv6RAMode: "ra-mode", + FilterByNeutronTags: infrav1.FilterByNeutronTags{ + Tags: []infrav1.NeutronTag{"tags"}, + TagsAny: []infrav1.NeutronTag{"tags-any"}, + NotTags: []infrav1.NeutronTag{"not-tags"}, + NotTagsAny: []infrav1.NeutronTag{"not-tags-any"}, + }, + }, }, }, }, @@ -382,7 +438,7 @@ func TestNetworksToPorts(t *testing.T) { after := infrav1.OpenStackMachine{} g.Expect(before.ConvertTo(&after)).To(gomega.Succeed()) - g.Expect(after.Spec).To(gomega.Equal(tt.afterMachineSpec)) + g.Expect(after.Spec).To(gomega.Equal(tt.afterMachineSpec), cmp.Diff(after.Spec, tt.afterMachineSpec)) }) } } @@ -399,27 +455,27 @@ func TestPortOptsConvertTo(t *testing.T) { // Variables used in the tests uuids := []string{"abc123", "123abc"} - securityGroupsUuids := []infrav1.SecurityGroupFilter{ - {ID: uuids[0]}, - {ID: uuids[1]}, + securityGroupsUuids := []infrav1.SecurityGroupParam{ + {ID: &uuids[0]}, + {ID: &uuids[1]}, } securityGroupFilter := []SecurityGroupParam{ {Name: "one"}, {UUID: "654cba"}, } - securityGroupFilterMerged := []infrav1.SecurityGroupFilter{ - {Name: "one"}, - {ID: "654cba"}, - {ID: uuids[0]}, - {ID: uuids[1]}, + securityGroupFilterMerged := []infrav1.SecurityGroupParam{ + {Filter: &infrav1.SecurityGroupFilter{Name: "one"}}, + {ID: ptr.To("654cba")}, + {ID: &uuids[0]}, + {ID: &uuids[1]}, } legacyPortProfile := map[string]string{ "capabilities": "[\"switchdev\"]", "trusted": "true", } convertedPortProfile := infrav1.BindingProfile{ - OVSHWOffload: true, - TrustedVF: true, + OVSHWOffload: ptr.To(true), + TrustedVF: ptr.To(true), } tests := []struct { @@ -437,8 +493,10 @@ func TestPortOptsConvertTo(t *testing.T) { SecurityGroups: uuids, }}, hubPortOpts: []infrav1.PortOpts{{ - Profile: convertedPortProfile, - SecurityGroupFilters: securityGroupsUuids, + ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{ + Profile: &convertedPortProfile, + }, + SecurityGroups: securityGroupsUuids, }}, }, { @@ -449,10 +507,17 @@ func TestPortOptsConvertTo(t *testing.T) { SecurityGroupFilters: securityGroupFilter, }}, hubPortOpts: []infrav1.PortOpts{{ - Profile: convertedPortProfile, - SecurityGroupFilters: securityGroupFilterMerged, + ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{ + Profile: &convertedPortProfile, + }, + SecurityGroups: securityGroupFilterMerged, }}, }, + { + name: "Empty port", + spokePortOpts: []PortOpts{{}}, + hubPortOpts: []infrav1.PortOpts{{}}, + }, } for _, tt := range tests { @@ -482,7 +547,7 @@ func TestPortOptsConvertTo(t *testing.T) { err := spokeMachineTemplate.ConvertTo(&convertedHub) g.Expect(err).NotTo(gomega.HaveOccurred()) // Comparing spec only here since the conversion will also add annotations that we don't care about for the test - g.Expect(convertedHub.Spec).To(gomega.Equal(hubMachineTemplate.Spec)) + g.Expect(convertedHub.Spec).To(gomega.Equal(hubMachineTemplate.Spec), cmp.Diff(convertedHub.Spec, hubMachineTemplate.Spec)) }) } } @@ -532,31 +597,31 @@ func TestMachineConversionControllerSpecFields(t *testing.T) { { name: "Set ProviderID", modifyUp: func(up *infrav1.OpenStackMachine) { - up.Spec.ProviderID = pointer.String("new-provider-id") + up.Spec.ProviderID = ptr.To("new-provider-id") }, testAfter: func(after *OpenStackMachine) { - g.Expect(after.Spec.ProviderID).To(gomega.Equal(pointer.String("new-provider-id"))) + g.Expect(after.Spec.ProviderID).To(gomega.Equal(ptr.To("new-provider-id"))) }, expectNetworkDiff: false, }, { name: "Set InstanceID", modifyUp: func(up *infrav1.OpenStackMachine) { - up.Spec.InstanceID = pointer.String("new-instance-id") + up.Status.InstanceID = ptr.To("new-instance-id") }, testAfter: func(after *OpenStackMachine) { - g.Expect(after.Spec.InstanceID).To(gomega.Equal(pointer.String("new-instance-id"))) + g.Expect(after.Spec.InstanceID).To(gomega.Equal(ptr.To("new-instance-id"))) }, expectNetworkDiff: false, }, { name: "Set ProviderID and non-ignored change", modifyUp: func(up *infrav1.OpenStackMachine) { - up.Spec.ProviderID = pointer.String("new-provider-id") + up.Spec.ProviderID = ptr.To("new-provider-id") up.Spec.Flavor = "new-flavor" }, testAfter: func(after *OpenStackMachine) { - g.Expect(after.Spec.ProviderID).To(gomega.Equal(pointer.String("new-provider-id"))) + g.Expect(after.Spec.ProviderID).To(gomega.Equal(ptr.To("new-provider-id"))) g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor")) }, expectNetworkDiff: true, @@ -591,3 +656,143 @@ func TestMachineConversionControllerSpecFields(t *testing.T) { }) } } + +func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t *testing.T) { + tests := []struct { + name string + in *OpenStackClusterSpec + expectedOut *infrav1.OpenStackClusterSpec + }{ + { + name: "empty", + in: &OpenStackClusterSpec{}, + expectedOut: &infrav1.OpenStackClusterSpec{}, + }, + { + name: "with managed security groups and not allow all in cluster traffic", + in: &OpenStackClusterSpec{ + ManagedSecurityGroups: true, + AllowAllInClusterTraffic: false, + }, + expectedOut: &infrav1.OpenStackClusterSpec{ + ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{ + AllNodesSecurityGroupRules: infrav1.LegacyCalicoSecurityGroupRules(), + }, + }, + }, + { + name: "with managed security groups and allow all in cluster traffic", + in: &OpenStackClusterSpec{ + ManagedSecurityGroups: true, + AllowAllInClusterTraffic: true, + }, + expectedOut: &infrav1.OpenStackClusterSpec{ + ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{ + AllowAllInClusterTraffic: true, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + out := &infrav1.OpenStackClusterSpec{} + err := Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in.DeepCopy(), out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(out).To(gomega.Equal(tt.expectedOut), cmp.Diff(out, tt.expectedOut)) + }) + + t.Run("template_"+tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + in := &OpenStackClusterTemplateSpec{ + Template: OpenStackClusterTemplateResource{ + Spec: *(tt.in.DeepCopy()), + }, + } + out := &infrav1.OpenStackClusterTemplateSpec{} + err := Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in, out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(&out.Template.Spec).To(gomega.Equal(tt.expectedOut), cmp.Diff(&out.Template.Spec, tt.expectedOut)) + }) + } +} + +func TestConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(t *testing.T) { + tests := []struct { + name string + in *OpenStackMachineSpec + expectedOut *infrav1.OpenStackMachineSpec + }{ + { + name: "empty", + in: &OpenStackMachineSpec{}, + expectedOut: &infrav1.OpenStackMachineSpec{}, + }, + { + name: "empty port", + in: &OpenStackMachineSpec{ + Ports: []PortOpts{{}}, + }, + expectedOut: &infrav1.OpenStackMachineSpec{ + Ports: []infrav1.PortOpts{{}}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + out := &infrav1.OpenStackMachineSpec{} + err := Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(tt.in.DeepCopy(), out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(out).To(gomega.Equal(tt.expectedOut), cmp.Diff(out, tt.expectedOut)) + }) + + t.Run("template_"+tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + in := &OpenStackMachineTemplateSpec{ + Template: OpenStackMachineTemplateResource{ + Spec: *(tt.in.DeepCopy()), + }, + } + out := &infrav1.OpenStackMachineTemplateSpec{} + err := Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in, out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(&out.Template.Spec).To(gomega.Equal(tt.expectedOut), cmp.Diff(&out.Template.Spec, tt.expectedOut)) + }) + } +} + +func Test_FuzzRestorers(t *testing.T) { + /* Cluster */ + testhelpers.FuzzRestorer(t, "restorev1alpha6ClusterSpec", restorev1alpha6ClusterSpec) + testhelpers.FuzzRestorer(t, "restorev1beta1ClusterSpec", restorev1beta1ClusterSpec) + testhelpers.FuzzRestorer(t, "restorev1alpha6ClusterStatus", restorev1alpha6ClusterStatus) + testhelpers.FuzzRestorer(t, "restorev1beta1ClusterStatus", restorev1beta1ClusterStatus) + testhelpers.FuzzRestorer(t, "restorev1beta1Bastion", restorev1beta1Bastion) + testhelpers.FuzzRestorer(t, "restorev1beta1BastionStatus", restorev1beta1BastionStatus) + + /* ClusterTemplate */ + testhelpers.FuzzRestorer(t, "restorev1beta1ClusterTemplateSpec", restorev1beta1ClusterTemplateSpec) + + /* Machine */ + testhelpers.FuzzRestorer(t, "restorev1alpha6MachineSpec", restorev1alpha6MachineSpec) + testhelpers.FuzzRestorer(t, "restorev1beta1MachineSpec", restorev1beta1MachineSpec) + + /* MachineTemplate */ + testhelpers.FuzzRestorer(t, "restorev1alpha6MachineTemplateMachineSpec", restorev1alpha6MachineTemplateMachineSpec) + + /* Types */ + testhelpers.FuzzRestorer(t, "restorev1alpha6SecurityGroupFilter", restorev1alpha6SecurityGroupFilter) + testhelpers.FuzzRestorer(t, "restorev1beta1SecurityGroupParam", restorev1beta1SecurityGroupParam) + testhelpers.FuzzRestorer(t, "restorev1alpha6NetworkFilter", restorev1alpha6NetworkFilter) + testhelpers.FuzzRestorer(t, "restorev1beta1NetworkParam", restorev1beta1NetworkParam) + testhelpers.FuzzRestorer(t, "restorev1alpha6SubnetFilter", restorev1alpha6SubnetFilter) + testhelpers.FuzzRestorer(t, "restorev1alpha6SubnetParam", restorev1alpha6SubnetParam) + testhelpers.FuzzRestorer(t, "restorev1beta1SubnetParam", restorev1beta1SubnetParam) + testhelpers.FuzzRestorer(t, "restorev1alpha6Port", restorev1alpha6Port) + testhelpers.FuzzRestorer(t, "restorev1beta1BlockDeviceVolume", restorev1beta1BlockDeviceVolume) + testhelpers.FuzzRestorer(t, "restorev1alpha6SecurityGroup", restorev1alpha6SecurityGroup) + testhelpers.FuzzRestorer(t, "restorev1beta1APIServerLoadBalancer", restorev1beta1APIServerLoadBalancer) +} diff --git a/api/v1alpha6/doc.go b/api/v1alpha6/doc.go index 721815c0fe..054e69741f 100644 --- a/api/v1alpha6/doc.go +++ b/api/v1alpha6/doc.go @@ -14,5 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7 +// Package v1alpha6 contains API Schema definitions for the infrastructure v1alpha6 API group. +// +kubebuilder:object:generate=true +// +groupName=infrastructure.cluster.x-k8s.io +// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1 package v1alpha6 diff --git a/api/v1alpha6/filter_convert.go b/api/v1alpha6/filter_convert.go deleted file mode 100644 index 6205bcd51f..0000000000 --- a/api/v1alpha6/filter_convert.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha6 - -import ( - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" -) - -func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts { - return subnets.ListOpts{ - Name: subnetFilter.Name, - Description: subnetFilter.Description, - ProjectID: subnetFilter.ProjectID, - IPVersion: subnetFilter.IPVersion, - GatewayIP: subnetFilter.GatewayIP, - CIDR: subnetFilter.CIDR, - IPv6AddressMode: subnetFilter.IPv6AddressMode, - IPv6RAMode: subnetFilter.IPv6RAMode, - ID: subnetFilter.ID, - Tags: subnetFilter.Tags, - TagsAny: subnetFilter.TagsAny, - NotTags: subnetFilter.NotTags, - NotTagsAny: subnetFilter.NotTagsAny, - } -} - -func (networkFilter NetworkFilter) ToListOpt() networks.ListOpts { - return networks.ListOpts{ - Name: networkFilter.Name, - Description: networkFilter.Description, - ProjectID: networkFilter.ProjectID, - ID: networkFilter.ID, - Tags: networkFilter.Tags, - TagsAny: networkFilter.TagsAny, - NotTags: networkFilter.NotTags, - NotTagsAny: networkFilter.NotTagsAny, - } -} diff --git a/api/v1alpha6/groupversion_info.go b/api/v1alpha6/groupversion_info.go index ffc696467f..1b2ae50550 100644 --- a/api/v1alpha6/groupversion_info.go +++ b/api/v1alpha6/groupversion_info.go @@ -14,9 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// package v1alpha6 contains API Schema definitions for the infrastructure v1alpha6 API group -// +kubebuilder:object:generate=true -// +groupName=infrastructure.cluster.x-k8s.io package v1alpha6 import ( diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go new file mode 100644 index 0000000000..665977d7e1 --- /dev/null +++ b/api/v1alpha6/openstackcluster_conversion.go @@ -0,0 +1,569 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha6 + +import ( + "reflect" + + apiconversion "k8s.io/apimachinery/pkg/conversion" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" + optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" +) + +var _ ctrlconversion.Convertible = &OpenStackCluster{} + +func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackCluster) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster, Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster, + v1alpha6OpenStackClusterRestorer, v1beta1OpenStackClusterRestorer, + ) +} + +func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackCluster) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster, + v1beta1OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackClusterList{} + +func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterList) + + return Convert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList(r, dst, nil) +} + +func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterList) + + return Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(src, r, nil) +} + +/* Restorers */ + +var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackCluster) *OpenStackClusterSpec { + return &c.Spec + }, + restorev1alpha6ClusterSpec, + // Filter out ControlPlaneEndpoint, which is written by the + // cluster controller + conversion.HashedFilterField[*OpenStackCluster]( + func(s *OpenStackClusterSpec) *OpenStackClusterSpec { + if s.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) { + f := *s + f.ControlPlaneEndpoint = clusterv1.APIEndpoint{} + return &f + } + return s + }, + ), + ), + "status": conversion.HashedFieldRestorer( + func(c *OpenStackCluster) *OpenStackClusterStatus { + return &c.Status + }, + restorev1alpha6ClusterStatus, + ), +} + +var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{ + "bastion": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackCluster) **infrav1.Bastion { + return &c.Spec.Bastion + }, + restorev1beta1Bastion, + ), + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterSpec { + return &c.Spec + }, + restorev1beta1ClusterSpec, + // Filter out Bastion, which is restored separately + conversion.HashedFilterField[*infrav1.OpenStackCluster, infrav1.OpenStackClusterSpec]( + func(s *infrav1.OpenStackClusterSpec) *infrav1.OpenStackClusterSpec { + if s.Bastion != nil { + f := *s + f.Bastion = nil + return &f + } + return s + }, + ), + ), + "status": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus { + return &c.Status + }, + restorev1beta1ClusterStatus, + ), +} + +/* OpenStackClusterSpec */ + +func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) { + if previous == nil || dst == nil { + return + } + + if len(previous.ExternalRouterIPs) == len(dst.ExternalRouterIPs) { + for i := range previous.ExternalRouterIPs { + dstIP := &dst.ExternalRouterIPs[i] + previousIP := &previous.ExternalRouterIPs[i] + + // Subnet.Filter.ID was overwritten in up-conversion by Subnet.UUID + dstIP.Subnet.Filter.ID = previousIP.Subnet.Filter.ID + + // If Subnet.UUID was previously unset, we overwrote it with the value of Subnet.Filter.ID + // Don't unset it again if it doesn't have the previous value of Subnet.Filter.ID, because that means it was genuinely changed + if previousIP.Subnet.UUID == "" && dstIP.Subnet.UUID == previousIP.Subnet.Filter.ID { + dstIP.Subnet.UUID = "" + } + } + } + + // We only restore DNSNameservers when these were lossly converted when NodeCIDR is empty. + if len(previous.DNSNameservers) > 0 && dst.NodeCIDR == "" { + dst.DNSNameservers = previous.DNSNameservers + } + + prevBastion := previous.Bastion + dstBastion := dst.Bastion + if prevBastion != nil && dstBastion != nil { + restorev1alpha6MachineSpec(&prevBastion.Instance, &dstBastion.Instance) + dstBastion.Instance.InstanceID = prevBastion.Instance.InstanceID + } + + // To avoid lossy conversion, we need to restore AllowAllInClusterTraffic + // even if ManagedSecurityGroups is set to false + if previous.AllowAllInClusterTraffic && !previous.ManagedSecurityGroups { + dst.AllowAllInClusterTraffic = true + } + + // Conversion to v1beta1 removes the Kind field + dst.IdentityRef = previous.IdentityRef + + if len(dst.ExternalRouterIPs) == len(previous.ExternalRouterIPs) { + for i := range dst.ExternalRouterIPs { + restorev1alpha6SubnetParam(&previous.ExternalRouterIPs[i].Subnet, &dst.ExternalRouterIPs[i].Subnet) + } + } + + restorev1alpha6SubnetFilter(&previous.Subnet, &dst.Subnet) + + restorev1alpha6NetworkFilter(&previous.Network, &dst.Network) +} + +func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) { + // Bastion is restored separately + + restorev1beta1NetworkParam(previous.Network, dst.Network) + + // ExternalNetwork by filter will be been lost in down-conversion + if previous.ExternalNetwork != nil { + if dst.ExternalNetwork == nil { + dst.ExternalNetwork = &infrav1.NetworkParam{} + } + dst.ExternalNetwork.Filter = previous.ExternalNetwork.Filter + } + + // Restore fields not present in v1alpha6 + dst.Router = previous.Router + dst.NetworkMTU = previous.NetworkMTU + dst.DisableExternalNetwork = previous.DisableExternalNetwork + + if len(previous.Subnets) > 0 && len(dst.Subnets) > 0 { + restorev1beta1SubnetParam(&previous.Subnets[0], &dst.Subnets[0]) + } + if len(previous.Subnets) > 1 { + dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...) + } + + if len(previous.ExternalRouterIPs) == len(dst.ExternalRouterIPs) { + for i := range dst.ExternalRouterIPs { + restorev1beta1SubnetParam(&previous.ExternalRouterIPs[i].Subnet, &dst.ExternalRouterIPs[i].Subnet) + } + } + + dst.ManagedSubnets = previous.ManagedSubnets + + if previous.ManagedSecurityGroups != nil && dst.ManagedSecurityGroups != nil { + dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules + } + + if dst.APIServerLoadBalancer != nil && previous.APIServerLoadBalancer != nil { + if dst.APIServerLoadBalancer.Enabled == nil || !*dst.APIServerLoadBalancer.Enabled { + dst.APIServerLoadBalancer.Enabled = previous.APIServerLoadBalancer.Enabled + } + optional.RestoreString(&previous.APIServerLoadBalancer.Provider, &dst.APIServerLoadBalancer.Provider) + + if previous.APIServerLoadBalancer.Network != nil { + dst.APIServerLoadBalancer.Network = previous.APIServerLoadBalancer.Network + } + if previous.APIServerLoadBalancer.Subnets != nil { + dst.APIServerLoadBalancer.Subnets = previous.APIServerLoadBalancer.Subnets + } + } + if dst.APIServerLoadBalancer.IsZero() { + dst.APIServerLoadBalancer = previous.APIServerLoadBalancer + } + + if dst.ControlPlaneEndpoint == nil || *dst.ControlPlaneEndpoint == (clusterv1.APIEndpoint{}) { + dst.ControlPlaneEndpoint = previous.ControlPlaneEndpoint + } + + optional.RestoreString(&previous.APIServerFloatingIP, &dst.APIServerFloatingIP) + optional.RestoreString(&previous.APIServerFixedIP, &dst.APIServerFixedIP) + optional.RestoreInt(&previous.APIServerPort, &dst.APIServerPort) + optional.RestoreBool(&previous.DisableAPIServerFloatingIP, &dst.DisableAPIServerFloatingIP) + optional.RestoreBool(&previous.ControlPlaneOmitAvailabilityZone, &dst.ControlPlaneOmitAvailabilityZone) + optional.RestoreBool(&previous.DisablePortSecurity, &dst.DisablePortSecurity) + + restorev1beta1APIServerLoadBalancer(previous.APIServerLoadBalancer, dst.APIServerLoadBalancer) +} + +func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Network != (NetworkFilter{}) { + out.Network = &infrav1.NetworkParam{} + if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(&in.Network, out.Network, s); err != nil { + return err + } + } + + if in.ExternalNetworkID != "" { + out.ExternalNetwork = &infrav1.NetworkParam{ + ID: &in.ExternalNetworkID, + } + } + + emptySubnet := SubnetFilter{} + if in.Subnet != emptySubnet { + subnet := infrav1.SubnetParam{} + if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &subnet, s); err != nil { + return err + } + out.Subnets = []infrav1.SubnetParam{subnet} + } + + // DNSNameservers without NodeCIDR doesn't make sense, so we drop that. + if len(in.NodeCIDR) > 0 { + out.ManagedSubnets = []infrav1.SubnetSpec{ + { + CIDR: in.NodeCIDR, + DNSNameservers: in.DNSNameservers, + }, + } + } + + if in.ManagedSecurityGroups { + out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{} + if !in.AllowAllInClusterTraffic { + out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules() + } else { + out.ManagedSecurityGroups.AllowAllInClusterTraffic = true + } + } + + if in.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) { + out.ControlPlaneEndpoint = &in.ControlPlaneEndpoint + } + + out.IdentityRef.CloudName = in.CloudName + if in.IdentityRef != nil { + out.IdentityRef.Name = in.IdentityRef.Name + } + + apiServerLoadBalancer := &infrav1.APIServerLoadBalancer{} + if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, apiServerLoadBalancer, s); err != nil { + return err + } + if !apiServerLoadBalancer.IsZero() { + out.APIServerLoadBalancer = apiServerLoadBalancer + } + + return nil +} + +func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s apiconversion.Scope) error { + return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in, out, s) +} + +func Convert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s apiconversion.Scope) error { + return autoConvert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in, out, s) +} + +func Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *infrav1.APIServerLoadBalancer, s apiconversion.Scope) error { + return autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s) +} + +func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Network != nil { + if err := Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkFilter(in.Network, &out.Network, s); err != nil { + return err + } + } + + if in.ExternalNetwork != nil && in.ExternalNetwork.ID != nil { + out.ExternalNetworkID = *in.ExternalNetwork.ID + } + + if len(in.Subnets) >= 1 { + if err := Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil { + return err + } + } + + if len(in.ManagedSubnets) > 0 { + out.NodeCIDR = in.ManagedSubnets[0].CIDR + out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers + } + + if in.ManagedSecurityGroups != nil { + out.ManagedSecurityGroups = true + out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic + } + + if in.ControlPlaneEndpoint != nil { + out.ControlPlaneEndpoint = *in.ControlPlaneEndpoint + } + + out.CloudName = in.IdentityRef.CloudName + out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name} + + if in.APIServerLoadBalancer != nil { + if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + return err + } + } + + return nil +} + +/* OpenStackClusterStatus */ + +func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) { + // PortOpts.SecurityGroups have been removed in v1beta1 + // We restore the whole PortOpts/Networks since they are anyway immutable. + if previous.ExternalNetwork != nil && dst.ExternalNetwork != nil { + dst.ExternalNetwork.PortOpts = previous.ExternalNetwork.PortOpts + } + if previous.Network != nil { + dst.Network = previous.Network + } + if previous.Bastion != nil && previous.Bastion.Networks != nil && dst.Bastion != nil { + dst.Bastion.Networks = previous.Bastion.Networks + } + + restorev1alpha6SecurityGroup(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup) + restorev1alpha6SecurityGroup(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup) + restorev1alpha6SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup) +} + +func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) { + // It's (theoretically) possible in v1beta1 to have Network nil but + // Router or APIServerLoadBalancer not nil. In hub-spoke-hub conversion this will + // result in Network being a pointer to an empty object. + if previous.Network == nil && dst.Network != nil && reflect.ValueOf(*dst.Network).IsZero() { + dst.Network = nil + } + + dst.ControlPlaneSecurityGroup = previous.ControlPlaneSecurityGroup + dst.WorkerSecurityGroup = previous.WorkerSecurityGroup + dst.BastionSecurityGroup = previous.BastionSecurityGroup + + restorev1beta1BastionStatus(previous.Bastion, dst.Bastion) + + if previous.APIServerLoadBalancer != nil { + dst.APIServerLoadBalancer = previous.APIServerLoadBalancer + } +} + +func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in, out, s) + if err != nil { + return err + } + + // Router and APIServerLoadBalancer have been moved out of Network in v1beta1 + if in.Router != nil || in.APIServerLoadBalancer != nil { + if out.Network == nil { + out.Network = &Network{} + } + + out.Network.Router = (*Router)(in.Router) + if in.APIServerLoadBalancer != nil { + out.Network.APIServerLoadBalancer = &LoadBalancer{ + Name: in.APIServerLoadBalancer.Name, + ID: in.APIServerLoadBalancer.ID, + IP: in.APIServerLoadBalancer.IP, + InternalIP: in.APIServerLoadBalancer.InternalIP, + AllowedCIDRs: in.APIServerLoadBalancer.AllowedCIDRs, + Tags: in.APIServerLoadBalancer.Tags, + } + } + } + + return nil +} + +func Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in, out, s) + if err != nil { + return err + } + + // Router and APIServerLoadBalancer have been moved out of Network in v1beta1 + if in.Network != nil { + out.Router = (*infrav1.Router)(in.Network.Router) + if in.Network.APIServerLoadBalancer != nil { + out.APIServerLoadBalancer = &infrav1.LoadBalancer{ + Name: in.Network.APIServerLoadBalancer.Name, + ID: in.Network.APIServerLoadBalancer.ID, + IP: in.Network.APIServerLoadBalancer.IP, + InternalIP: in.Network.APIServerLoadBalancer.InternalIP, + AllowedCIDRs: in.Network.APIServerLoadBalancer.AllowedCIDRs, + Tags: in.Network.APIServerLoadBalancer.Tags, + } + } + } + + return nil +} + +/* Bastion */ + +func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) { + if previous == nil || dst == nil || *previous == nil || *dst == nil { + return + } + if *dst != nil && (*previous).Spec != nil && (*dst).Spec != nil { + restorev1beta1MachineSpec((*previous).Spec, (*dst).Spec) + } + + optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP) + optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone) + optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled) +} + +func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in, out, s) + if err != nil { + return err + } + + if !reflect.ValueOf(in.Instance).IsZero() { + out.Spec = &infrav1.OpenStackMachineSpec{} + + err = Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Spec, s) + if err != nil { + return err + } + + if in.Instance.ServerGroupID != "" { + out.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: &in.Instance.ServerGroupID} + } else { + out.Spec.ServerGroup = nil + } + + err = optional.Convert_string_To_optional_String(&in.Instance.FloatingIP, &out.FloatingIP, s) + if err != nil { + return err + } + } + + // nil the Spec if it's basically an empty object. + if out.Spec != nil && reflect.ValueOf(*out.Spec).IsZero() { + out.Spec = nil + } + return nil +} + +func Convert_v1beta1_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error { + err := autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in, out, s) + if err != nil { + return err + } + + if in.Spec != nil { + err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in.Spec, &out.Instance, s) + if err != nil { + return err + } + + if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != nil { + out.Instance.ServerGroupID = *in.Spec.ServerGroup.ID + } + } + + return optional.Convert_optional_String_To_string(&in.FloatingIP, &out.Instance.FloatingIP, s) +} + +/* Bastion status */ + +func restorev1beta1BastionStatus(previous *infrav1.BastionStatus, dst *infrav1.BastionStatus) { + if previous == nil || dst == nil { + return + } + + // Resolved and resources have no equivalents + dst.Resolved = previous.Resolved + dst.Resources = previous.Resources +} + +func Convert_v1alpha6_Instance_To_v1beta1_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ apiconversion.Scope) error { + // BastionStatus is the same as Spec with unused fields removed + out.ID = in.ID + out.Name = in.Name + out.SSHKeyName = in.SSHKeyName + out.State = infrav1.InstanceState(in.State) + out.IP = in.IP + out.FloatingIP = in.FloatingIP + return nil +} + +func Convert_v1beta1_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStatus, out *Instance, _ apiconversion.Scope) error { + // BastionStatus is the same as Spec with unused fields removed + out.ID = in.ID + out.Name = in.Name + out.SSHKeyName = in.SSHKeyName + out.State = InstanceState(in.State) + out.IP = in.IP + out.FloatingIP = in.FloatingIP + return nil +} diff --git a/api/v1alpha6/openstackcluster_types.go b/api/v1alpha6/openstackcluster_types.go index 6b60c83b9e..e3a0d82a42 100644 --- a/api/v1alpha6/openstackcluster_types.go +++ b/api/v1alpha6/openstackcluster_types.go @@ -212,7 +212,10 @@ type OpenStackClusterStatus struct { FailureMessage *string `json:"failureMessage,omitempty"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true +// +kubebuilder:deprecatedversion:warning="The v1alpha6 version of OpenStackCluster has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackclusters,scope=Namespaced,categories=cluster-api,shortName=osc // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this OpenStackCluster belongs" @@ -224,6 +227,8 @@ type OpenStackClusterStatus struct { // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of OpenStackCluster" // OpenStackCluster is the Schema for the openstackclusters API. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackCluster struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -235,6 +240,8 @@ type OpenStackCluster struct { // +kubebuilder:object:root=true // OpenStackClusterList contains a list of OpenStackCluster. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackClusterList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` diff --git a/api/v1alpha6/openstackclustertemplate_conversion.go b/api/v1alpha6/openstackclustertemplate_conversion.go new file mode 100644 index 0000000000..7ded0fc0de --- /dev/null +++ b/api/v1alpha6/openstackclustertemplate_conversion.go @@ -0,0 +1,83 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha6 + +import ( + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" +) + +var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{} + +func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterTemplate) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate, Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, + v1alpha6OpenStackClusterTemplateRestorer, v1beta1OpenStackClusterTemplateRestorer, + ) +} + +func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterTemplate) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate, + v1beta1OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackClusterTemplateList{} + +func (r *OpenStackClusterTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterTemplateList) + return Convert_v1alpha6_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(r, dst, nil) +} + +func (r *OpenStackClusterTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterTemplateList) + return Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(src, r, nil) +} + +/* Restorers */ + +var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackClusterTemplate) *OpenStackClusterSpec { + return &c.Spec.Template.Spec + }, + restorev1alpha6ClusterSpec, + ), +} + +var v1beta1OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackClusterTemplate) *infrav1.OpenStackClusterTemplateSpec { + return &c.Spec + }, + restorev1beta1ClusterTemplateSpec, + ), +} + +func restorev1beta1ClusterTemplateSpec(previous *infrav1.OpenStackClusterTemplateSpec, dst *infrav1.OpenStackClusterTemplateSpec) { + restorev1beta1Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion) + restorev1beta1ClusterSpec(&previous.Template.Spec, &dst.Template.Spec) +} diff --git a/api/v1alpha6/openstackclustertemplate_types.go b/api/v1alpha6/openstackclustertemplate_types.go index f79730240c..8e5115a793 100644 --- a/api/v1alpha6/openstackclustertemplate_types.go +++ b/api/v1alpha6/openstackclustertemplate_types.go @@ -30,10 +30,15 @@ type OpenStackClusterTemplateSpec struct { Template OpenStackClusterTemplateResource `json:"template"` } -//+kubebuilder:object:root=true -//+kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct +// +genclient +// +genclient:Namespaced +// +kubebuilder:object:root=true +// +kubebuilder:deprecatedversion:warning="The v1alpha6 version of OpenStackClusterTemplate has been deprecated and will be removed in a future release of the API. Please upgrade." +// +kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct // OpenStackClusterTemplate is the Schema for the openstackclustertemplates API. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackClusterTemplate struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -41,9 +46,11 @@ type OpenStackClusterTemplate struct { Spec OpenStackClusterTemplateSpec `json:"spec,omitempty"` } -//+kubebuilder:object:root=true +// +kubebuilder:object:root=true // OpenStackClusterTemplateList contains a list of OpenStackClusterTemplate. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackClusterTemplateList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go new file mode 100644 index 0000000000..aed2d3b7d4 --- /dev/null +++ b/api/v1alpha6/openstackmachine_conversion.go @@ -0,0 +1,388 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha6 + +import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" +) + +var _ ctrlconversion.Convertible = &OpenStackMachine{} + +func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachine) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine, Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine, + v1alpha6OpenStackMachineRestorer, v1beta1OpenStackMachineRestorer, + ) +} + +func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachine) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine, + v1beta1OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackMachineList{} + +func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachineList) + return Convert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(r, dst, nil) +} + +func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachineList) + return Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(src, r, nil) +} + +/* Restorers */ + +var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackMachine) *OpenStackMachineSpec { + return &c.Spec + }, + restorev1alpha6MachineSpec, + conversion.HashedFilterField[*OpenStackMachine, OpenStackMachineSpec](func(s *OpenStackMachineSpec) *OpenStackMachineSpec { + // Despite being spec fields, ProviderID and InstanceID + // are both set by the machine controller. If these are + // the only changes to the spec, we still want to + // restore the rest of the spec to its original state. + if s.ProviderID != nil || s.InstanceID != nil { + f := *s + f.ProviderID = nil + f.InstanceID = nil + return &f + } + return s + }), + ), +} + +var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{ + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec { + return &c.Spec + }, + restorev1beta1MachineSpec, + ), + "depresources": conversion.UnconditionalFieldRestorer( + func(c *infrav1.OpenStackMachine) **infrav1.MachineResources { + return &c.Status.Resources + }, + ), + // No equivalent in v1alpha6 + "refresources": conversion.UnconditionalFieldRestorer( + func(c *infrav1.OpenStackMachine) **infrav1.ResolvedMachineSpec { + return &c.Status.Resolved + }, + ), +} + +/* OpenStackMachine */ + +func Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *infrav1.OpenStackMachine, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s) + if err != nil { + return err + } + out.Status.InstanceID = in.Spec.InstanceID + return nil +} + +func Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *infrav1.OpenStackMachine, out *OpenStackMachine, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in, out, s) + if err != nil { + return err + } + out.Spec.InstanceID = in.Status.InstanceID + return nil +} + +/* OpenStackMachineSpec */ + +func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) { + // Subnet is removed from v1beta1 with no replacement, so can't be + // losslessly converted. Restore the previously stored value on down-conversion. + dst.Subnet = previous.Subnet + + // Strictly speaking this is lossy because we lose changes in + // down-conversion which were made to the up-converted object. However + // it isn't worth implementing this as the fields are immutable. + dst.Networks = previous.Networks + dst.Ports = previous.Ports + dst.SecurityGroups = previous.SecurityGroups + + // FloatingIP is removed from v1alpha7 with no replacement, so can't be + // losslessly converted. Restore the previously stored value on down-conversion. + dst.FloatingIP = previous.FloatingIP + + // Conversion to v1beta1 truncates keys and values to 255 characters + for k, v := range previous.ServerMetadata { + kd := k + if len(k) > 255 { + kd = k[:255] + } + + vd := v + if len(v) > 255 { + vd = v[:255] + } + + if kd != k || vd != v { + if dst.ServerMetadata == nil { + dst.ServerMetadata = make(map[string]string) + } + delete(dst.ServerMetadata, kd) + dst.ServerMetadata[k] = v + } + } + + // Conversion to v1beta1 removes the Kind fild + dst.IdentityRef = previous.IdentityRef + + if len(dst.Ports) == len(previous.Ports) { + for i := range dst.Ports { + restorev1alpha6Port(&previous.Ports[i], &dst.Ports[i]) + } + } + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for i := range dst.SecurityGroups { + restorev1alpha6SecurityGroupFilter(&previous.SecurityGroups[i].Filter, &dst.SecurityGroups[i].Filter) + } + } + + // Conversion to v1beta1 removes Image when ImageUUID is set + if dst.Image == "" && previous.Image != "" { + dst.Image = previous.Image + } +} + +func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) { + // PropagateUplinkStatus has been added in v1beta1. + // We restore the whole Ports since they are anyway immutable. + dst.Ports = previous.Ports + dst.AdditionalBlockDevices = previous.AdditionalBlockDevices + dst.ServerGroup = previous.ServerGroup + dst.Image = previous.Image + dst.FloatingIPPoolRef = previous.FloatingIPPoolRef + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for i := range dst.SecurityGroups { + restorev1beta1SecurityGroupParam(&previous.SecurityGroups[i], &dst.SecurityGroups[i]) + } + } + + if dst.RootVolume != nil && previous.RootVolume != nil { + restorev1beta1BlockDeviceVolume( + &previous.RootVolume.BlockDeviceVolume, + &dst.RootVolume.BlockDeviceVolume, + ) + } + + if len(dst.AdditionalBlockDevices) == len(previous.AdditionalBlockDevices) { + for i := range dst.AdditionalBlockDevices { + restorev1beta1BlockDeviceVolume( + previous.AdditionalBlockDevices[i].Storage.Volume, + dst.AdditionalBlockDevices[i].Storage.Volume, + ) + } + } +} + +func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]infrav1.PortOpts, error) { + var ports []infrav1.PortOpts + + for i := range networks { + network := networks[i] + + // This will remain null if the network is not specified in NetworkParam + var networkFilter *infrav1.NetworkParam + + // In v1alpha6, if network.Filter resolved to multiple networks + // then we would add multiple ports. It is not possible to + // support this behaviour during k8s API conversion as it + // requires an OpenStack API call. A network filter returning + // multiple networks now becomes an error when we attempt to + // create the port. + switch { + case network.UUID != "": + networkFilter = &infrav1.NetworkParam{ + ID: &network.UUID, + } + case network.Filter != (NetworkFilter{}): + networkFilter = &infrav1.NetworkParam{} + if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(&network.Filter, networkFilter, s); err != nil { + return nil, err + } + } + + // Note that network.FixedIP was unused in v1alpha6 so we also ignore it here. + + // In v1alpha6, specifying multiple subnets created multiple + // ports. We maintain this behaviour in conversion by adding + // multiple portOpts in this case. + // + // Also, similar to network.Filter above, if a subnet filter + // resolved to multiple subnets then we would add a port for + // each subnet. Again, it is not possible to support this + // behaviour during k8s API conversion as it requires an + // OpenStack API call. A subnet filter returning multiple + // subnets now becomes an error when we attempt to create the + // port. + if len(network.Subnets) == 0 { + // If the network has no explicit subnets then we create a single port with no subnets. + ports = append(ports, infrav1.PortOpts{Network: networkFilter}) + } else { + // If the network has explicit subnets then we create a separate port for each subnet. + for i := range network.Subnets { + subnet := network.Subnets[i] + if subnet.UUID != "" { + ports = append(ports, infrav1.PortOpts{ + Network: networkFilter, + FixedIPs: []infrav1.FixedIP{ + {Subnet: &infrav1.SubnetParam{ID: &subnet.UUID}}, + }, + }) + } else { + subnetParam := &infrav1.SubnetParam{} + if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(&subnet.Filter, subnetParam, s); err != nil { + return nil, err + } + ports = append(ports, infrav1.PortOpts{ + Network: networkFilter, + FixedIPs: []infrav1.FixedIP{ + {Subnet: subnetParam}, + }, + }) + } + } + } + } + + return ports, nil +} + +func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in, out, s) + if err != nil { + return err + } + + if len(in.Networks) > 0 { + ports, err := convertNetworksToPorts(in.Networks, s) + if err != nil { + return err + } + // Networks were previously created first, so need to come before ports + out.Ports = append(ports, out.Ports...) + } + + if in.ServerGroupID != "" { + out.ServerGroup = &infrav1.ServerGroupParam{ID: &in.ServerGroupID} + } else { + out.ServerGroup = nil + } + + imageParam := infrav1.ImageParam{} + if in.ImageUUID != "" { + imageParam.ID = &in.ImageUUID + } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both. + imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image} + } + out.Image = imageParam + + if len(in.ServerMetadata) > 0 { + serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata)) + for k, v := range in.ServerMetadata { + // Truncate key and value to 255 characters if required, as this + // was not validated prior to v1beta1 + if len(k) > 255 { + k = k[:255] + } + if len(v) > 255 { + v = v[:255] + } + + serverMetadata = append(serverMetadata, infrav1.ServerMetadata{Key: k, Value: v}) + } + out.ServerMetadata = serverMetadata + } + + if in.IdentityRef != nil { + out.IdentityRef = &infrav1.OpenStackIdentityReference{Name: in.IdentityRef.Name} + } + if in.CloudName != "" { + if out.IdentityRef == nil { + out.IdentityRef = &infrav1.OpenStackIdentityReference{} + } + out.IdentityRef.CloudName = in.CloudName + } + + return nil +} + +func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s) + if err != nil { + return err + } + + if in.ServerGroup != nil && in.ServerGroup.ID != nil { + out.ServerGroupID = *in.ServerGroup.ID + } + + if in.Image.ID != nil { + out.ImageUUID = *in.Image.ID + } else if in.Image.Filter != nil && in.Image.Filter.Name != nil { + out.Image = *in.Image.Filter.Name + } + + if len(in.ServerMetadata) > 0 { + serverMetadata := make(map[string]string, len(in.ServerMetadata)) + for i := range in.ServerMetadata { + key := in.ServerMetadata[i].Key + value := in.ServerMetadata[i].Value + serverMetadata[key] = value + } + out.ServerMetadata = serverMetadata + } + + if in.IdentityRef != nil { + out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name} + out.CloudName = in.IdentityRef.CloudName + } + + return nil +} + +/* OpenStackMachineStatus */ + +func Convert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error { + // ReferencedResources have no equivalent in v1alpha6 + return autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s) +} diff --git a/api/v1alpha6/openstackmachine_types.go b/api/v1alpha6/openstackmachine_types.go index c73505de3f..9f306cba1d 100644 --- a/api/v1alpha6/openstackmachine_types.go +++ b/api/v1alpha6/openstackmachine_types.go @@ -19,7 +19,7 @@ package v1alpha6 import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/errors" ) @@ -136,7 +136,10 @@ type OpenStackMachineStatus struct { Conditions clusterv1.Conditions `json:"conditions,omitempty"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true +// +kubebuilder:deprecatedversion:warning="The v1alpha6 version of OpenStackMachine has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackmachines,scope=Namespaced,categories=cluster-api,shortName=osm // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this OpenStackMachine belongs" @@ -147,6 +150,8 @@ type OpenStackMachineStatus struct { // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of OpenStackMachine" // OpenStackMachine is the Schema for the openstackmachines API. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackMachine struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -158,6 +163,8 @@ type OpenStackMachine struct { // +kubebuilder:object:root=true // OpenStackMachineList contains a list of OpenStackMachine. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackMachineList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` @@ -177,7 +184,7 @@ func (r *OpenStackMachine) SetConditions(conditions clusterv1.Conditions) { // SetFailure sets the OpenStackMachine status failure reason and failure message. func (r *OpenStackMachine) SetFailure(failureReason errors.MachineStatusError, failureMessage error) { r.Status.FailureReason = &failureReason - r.Status.FailureMessage = pointer.String(failureMessage.Error()) + r.Status.FailureMessage = ptr.To(failureMessage.Error()) } func init() { diff --git a/api/v1alpha6/openstackmachinetemplate_conversion.go b/api/v1alpha6/openstackmachinetemplate_conversion.go new file mode 100644 index 0000000000..f18681d5e3 --- /dev/null +++ b/api/v1alpha6/openstackmachinetemplate_conversion.go @@ -0,0 +1,88 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha6 + +import ( + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" +) + +var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{} + +func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachineTemplate) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate, Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, + v1alpha6OpenStackMachineTemplateRestorer, v1beta1OpenStackMachineTemplateRestorer, + ) +} + +func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachineTemplate) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate, + v1beta1OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{} + +func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachineTemplateList) + return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(r, dst, nil) +} + +func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachineTemplateList) + return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(src, r, nil) +} + +/* Restorers */ + +var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackMachineTemplate) *OpenStackMachineSpec { + return &c.Spec.Template.Spec + }, + restorev1alpha6MachineTemplateMachineSpec, + ), +} + +var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec { + return &c.Spec.Template.Spec + }, + restorev1beta1MachineSpec, + ), +} + +// Restore a MachineSpec in the context of a MachineTemplate. Restores +// InstanceID, which will not otherwise be restored for a MachineTemplate. +func restorev1alpha6MachineTemplateMachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) { + if previous == nil || dst == nil { + return + } + restorev1alpha6MachineSpec(previous, dst) + dst.InstanceID = previous.InstanceID +} diff --git a/api/v1alpha6/openstackmachinetemplate_types.go b/api/v1alpha6/openstackmachinetemplate_types.go index aca2be9c70..d1fd2f0895 100644 --- a/api/v1alpha6/openstackmachinetemplate_types.go +++ b/api/v1alpha6/openstackmachinetemplate_types.go @@ -25,10 +25,15 @@ type OpenStackMachineTemplateSpec struct { Template OpenStackMachineTemplateResource `json:"template"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true +// +kubebuilder:deprecatedversion:warning="The v1alpha6 version of OpenStackMachineTemplate has been deprecated and will be removed in a future release of the API. Please upgrade." // +kubebuilder:resource:path=openstackmachinetemplates,scope=Namespaced,categories=cluster-api,shortName=osmt // OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackMachineTemplate struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -39,6 +44,8 @@ type OpenStackMachineTemplate struct { // +kubebuilder:object:root=true // OpenStackMachineTemplateList contains a list of OpenStackMachineTemplate. +// +// Deprecated: This type will be removed in one of the next releases. type OpenStackMachineTemplateList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` diff --git a/api/v1alpha6/types.go b/api/v1alpha6/types.go index 2e81c35fd2..d93cde281a 100644 --- a/api/v1alpha6/types.go +++ b/api/v1alpha6/types.go @@ -119,8 +119,10 @@ type PortOpts struct { ProjectID string `json:"projectId,omitempty"` // The uuids of the security groups to assign to the instance // +listType=set + // +k8s:conversion-gen=false SecurityGroups []string `json:"securityGroups,omitempty"` // The names, uuids, filters or any combination these of the security groups to assign to the instance + // +k8s:conversion-gen=false SecurityGroupFilters []SecurityGroupParam `json:"securityGroupFilters,omitempty"` AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"` // Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited. @@ -251,7 +253,7 @@ type LoadBalancer struct { type SecurityGroup struct { Name string `json:"name"` ID string `json:"id"` - Rules []SecurityGroupRule `json:"rules"` + Rules []SecurityGroupRule `json:"rules,omitempty"` } // SecurityGroupRule represent the basic information of the associated OpenStack @@ -285,8 +287,8 @@ func (r SecurityGroupRule) Equal(x SecurityGroupRule) bool { type InstanceState string var ( - // InstanceStateBuilding is the string representing an instance in a building state. - InstanceStateBuilding = InstanceState("BUILDING") + // InstanceStateBuild is the string representing an instance in a build state. + InstanceStateBuild = InstanceState("BUILD") // InstanceStateActive is the string representing an instance in an active state. InstanceStateActive = InstanceState("ACTIVE") @@ -302,6 +304,9 @@ var ( // InstanceStateDeleted is the string representing an instance in a deleted state. InstanceStateDeleted = InstanceState("DELETED") + + // InstanceStateUndefined is the string representing an undefined instance state. + InstanceStateUndefined = InstanceState("") ) // Bastion represents basic information about the bastion node. diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go new file mode 100644 index 0000000000..041ce9eb3a --- /dev/null +++ b/api/v1alpha6/types_conversion.go @@ -0,0 +1,570 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha6 + +import ( + "errors" + "strings" + + apiconversion "k8s.io/apimachinery/pkg/conversion" + "k8s.io/utils/ptr" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversioncommon" + optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" +) + +const trueString = "true" + +/* ExternalRouterIPParam */ +/* SecurityGroupParam, SecurityGroupFilter */ + +func restorev1alpha6SecurityGroupFilter(previous *SecurityGroupFilter, dst *SecurityGroupFilter) { + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny +} + +func restorev1beta1SecurityGroupParam(previous *infrav1.SecurityGroupParam, dst *infrav1.SecurityGroupParam) { + if previous == nil || dst == nil { + return + } + + if dst.Filter != nil && previous.Filter != nil { + dst.Filter.Tags = previous.Filter.Tags + dst.Filter.TagsAny = previous.Filter.TagsAny + dst.Filter.NotTags = previous.Filter.NotTags + dst.Filter.NotTagsAny = previous.Filter.NotTagsAny + } +} + +func Convert_v1beta1_SecurityGroupParam_To_string(in *infrav1.SecurityGroupParam, out *string, _ apiconversion.Scope) error { + if in.ID != nil { + *out = *in.ID + } + return nil +} + +func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *infrav1.SecurityGroupParam, s apiconversion.Scope) error { + if in.UUID != "" { + out.ID = &in.UUID + return nil + } + + outFilter := &infrav1.SecurityGroupFilter{} + + if in.Name != "" { + outFilter.Name = in.Name + } else { + err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, outFilter, s) + if err != nil { + return err + } + } + + if !outFilter.IsZero() { + out.Filter = outFilter + } + return nil +} + +func Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupParam, out *SecurityGroupParam, s apiconversion.Scope) error { + if in.ID != nil { + out.UUID = *in.ID + return nil + } + + if in.Filter != nil { + err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in.Filter, &out.Filter, s) + if err != nil { + return err + } + } + + return nil +} + +func Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s) + if err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags) + return nil +} + +func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s apiconversion.Scope) error { + if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + return nil +} + +/* NetworkParam, NetworkFilter */ + +func restorev1alpha6NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) { + if previous == nil || dst == nil { + return + } + + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny + + if dst.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + } +} + +func restorev1beta1NetworkParam(previous *infrav1.NetworkParam, dst *infrav1.NetworkParam) { + if previous == nil || dst == nil { + return + } + + if dst.Filter != nil && previous.Filter != nil { + dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags + } +} + +func Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(in *NetworkFilter, out *infrav1.NetworkParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + outFilter := &infrav1.NetworkFilter{} + if err := autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, outFilter, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &outFilter.FilterByNeutronTags) + if !outFilter.IsZero() { + out.Filter = outFilter + } + return nil +} + +func Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkFilter(in *infrav1.NetworkParam, out *NetworkFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + if in.Filter != nil { + if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + } + return nil +} + +/* SubnetParam, SubnetFilter */ + +func restorev1alpha6SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) { + if previous == nil || dst == nil { + return + } + + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny + + // We didn't convert other fields if ID was set + if previous.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + dst.IPVersion = previous.IPVersion + dst.GatewayIP = previous.GatewayIP + dst.CIDR = previous.CIDR + dst.IPv6AddressMode = previous.IPv6AddressMode + dst.IPv6RAMode = previous.IPv6RAMode + } +} + +func restorev1alpha6SubnetParam(previous *SubnetParam, dst *SubnetParam) { + if previous == nil || dst == nil { + return + } + + if previous.UUID != "" { + dst.Filter = previous.Filter + } else { + restorev1alpha6SubnetFilter(&previous.Filter, &dst.Filter) + } +} + +func restorev1beta1SubnetParam(previous *infrav1.SubnetParam, dst *infrav1.SubnetParam) { + if previous == nil || dst == nil { + return + } + + optional.RestoreString(&previous.ID, &dst.ID) + + if previous.Filter != nil && dst.Filter != nil { + dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags + } +} + +func Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetParam(in *SubnetParam, out *infrav1.SubnetParam, s apiconversion.Scope) error { + if in.UUID != "" { + out.ID = &in.UUID + return nil + } + + outFilter := &infrav1.SubnetFilter{} + if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, outFilter, s); err != nil { + return err + } + if !outFilter.IsZero() { + out.Filter = outFilter + } + return nil +} + +func Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetParam(in *infrav1.SubnetParam, out *SubnetParam, s apiconversion.Scope) error { + if in.ID != nil { + out.UUID = *in.ID + return nil + } + + if in.Filter != nil { + if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in.Filter, &out.Filter, s); err != nil { + return err + } + } + + return nil +} + +func Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *infrav1.SubnetFilter, s apiconversion.Scope) error { + if err := autoConvert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags) + return nil +} + +func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *infrav1.SubnetFilter, out *SubnetFilter, s apiconversion.Scope) error { + if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + return nil +} + +func Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(in *SubnetFilter, out *infrav1.SubnetParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + + outFilter := &infrav1.SubnetFilter{} + if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in, outFilter, s); err != nil { + return err + } + if !outFilter.IsZero() { + out.Filter = outFilter + } + return nil +} + +func Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetFilter(in *infrav1.SubnetParam, out *SubnetFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + + if in.Filter != nil { + if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in.Filter, out, s); err != nil { + return err + } + } + return nil +} + +/* PortOpts, BindingProfile */ + +func restorev1alpha6Port(previous *PortOpts, dst *PortOpts) { + if len(dst.SecurityGroupFilters) == len(previous.SecurityGroupFilters) { + for i := range dst.SecurityGroupFilters { + restorev1alpha6SecurityGroupFilter(&previous.SecurityGroupFilters[i].Filter, &dst.SecurityGroupFilters[i].Filter) + } + } + + restorev1alpha6NetworkFilter(previous.Network, dst.Network) + + if len(dst.FixedIPs) == len(previous.FixedIPs) { + for i := range dst.FixedIPs { + prevFixedIP := &previous.FixedIPs[i] + dstFixedIP := &dst.FixedIPs[i] + + if dstFixedIP.Subnet != nil && prevFixedIP.Subnet != nil { + restorev1alpha6SubnetFilter(prevFixedIP.Subnet, dstFixedIP.Subnet) + } + } + } +} + +func Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error { + if err := autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in, out, s); err != nil { + return err + } + + if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 { + out.SecurityGroups = make([]infrav1.SecurityGroupParam, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) + for i := range in.SecurityGroupFilters { + if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil { + return err + } + } + for i := range in.SecurityGroups { + out.SecurityGroups[i+len(in.SecurityGroupFilters)] = infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]} + } + } + + // Profile is now a struct in v1beta1. + var ovsHWOffload, trustedVF bool + if strings.Contains(in.Profile["capabilities"], "switchdev") { + ovsHWOffload = true + } + if in.Profile["trusted"] == trueString { + trustedVF = true + } + if ovsHWOffload || trustedVF { + out.Profile = &infrav1.BindingProfile{} + if ovsHWOffload { + out.Profile.OVSHWOffload = &ovsHWOffload + } + if trustedVF { + out.Profile.TrustedVF = &trustedVF + } + } + + return nil +} + +func Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error { + if err := autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in, out, s); err != nil { + return err + } + + // The auto-generated function converts v1beta1 SecurityGroup to + // v1alpha6 SecurityGroup, but v1alpha6 SecurityGroupFilter is more + // appropriate. Unset them and convert to SecurityGroupFilter instead. + out.SecurityGroups = nil + if len(in.SecurityGroups) > 0 { + out.SecurityGroupFilters = make([]SecurityGroupParam, len(in.SecurityGroups)) + for i := range in.SecurityGroups { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { + return err + } + } + } + + if in.Profile != nil { + out.Profile = make(map[string]string) + if ptr.Deref(in.Profile.OVSHWOffload, false) { + (out.Profile)["capabilities"] = "[\"switchdev\"]" + } + if ptr.Deref(in.Profile.TrustedVF, false) { + (out.Profile)["trusted"] = trueString + } + } + + return nil +} + +func Convert_Map_string_To_Interface_To_v1beta1_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ apiconversion.Scope) error { + for k, v := range in { + if k == "capabilities" { + if strings.Contains(v, "switchdev") { + out.OVSHWOffload = ptr.To(true) + } + } + if k == "trusted" && v == trueString { + out.TrustedVF = ptr.To(true) + } + } + return nil +} + +func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error { + if ptr.Deref(in.OVSHWOffload, false) { + (out)["capabilities"] = "[\"switchdev\"]" + } + if ptr.Deref(in.TrustedVF, false) { + (out)["trusted"] = trueString + } + return nil +} + +/* FixedIP */ +/* AddressPair */ +/* Instance */ +/* RootVolume */ + +func restorev1beta1BlockDeviceVolume(previous *infrav1.BlockDeviceVolume, dst *infrav1.BlockDeviceVolume) { + if previous == nil || dst == nil { + return + } + + dstAZ := dst.AvailabilityZone + previousAZ := previous.AvailabilityZone + + // Empty From (the default) will be converted to the explicit "Name" + if dstAZ != nil && previousAZ != nil && dstAZ.From == "Name" { + dstAZ.From = previousAZ.From + } +} + +func Convert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *infrav1.RootVolume, s apiconversion.Scope) error { + out.SizeGiB = in.Size + out.Type = in.VolumeType + return conversioncommon.Convert_string_To_Pointer_v1beta1_VolumeAvailabilityZone(&in.AvailabilityZone, &out.AvailabilityZone, s) +} + +func Convert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in *infrav1.RootVolume, out *RootVolume, s apiconversion.Scope) error { + out.Size = in.SizeGiB + out.VolumeType = in.Type + return conversioncommon.Convert_Pointer_v1beta1_VolumeAvailabilityZone_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s) +} + +/* Network */ + +func Convert_v1alpha6_Network_To_v1beta1_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s apiconversion.Scope) error { + // PortOpts has been removed in v1beta1 + err := Convert_v1alpha6_Network_To_v1beta1_NetworkStatus(in, &out.NetworkStatus, s) + if err != nil { + return err + } + + if in.Subnet != nil { + out.Subnets = []infrav1.Subnet{infrav1.Subnet(*in.Subnet)} + } + return nil +} + +func Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha6_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s apiconversion.Scope) error { + // PortOpts has been removed in v1beta1 + err := Convert_v1beta1_NetworkStatus_To_v1alpha6_Network(&in.NetworkStatus, out, s) + if err != nil { + return err + } + + // Can only down-convert a single subnet + if len(in.Subnets) > 0 { + out.Subnet = (*Subnet)(&in.Subnets[0]) + } + return nil +} + +func Convert_v1alpha6_Network_To_v1beta1_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ apiconversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + out.Tags = in.Tags + + return nil +} + +func Convert_v1beta1_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatus, out *Network, _ apiconversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + out.Tags = in.Tags + + return nil +} + +/* Subnet */ +/* Router */ +/* LoadBalancer */ +/* SecurityGroup */ + +func restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) { + if previous == nil || dst == nil { + return + } + + dst.Rules = previous.Rules +} + +func Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, _ apiconversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + return nil +} + +func Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, _ apiconversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + return nil +} + +/* SecurityGroupRule */ +/* ValueSpec */ +/* OpenStackIdentityReference */ + +func Convert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error { + return autoConvert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in, out, s) +} + +func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *infrav1.OpenStackIdentityReference, out *OpenStackIdentityReference, _ apiconversion.Scope) error { + out.Name = in.Name + return nil +} + +/* APIServerLoadBalancer */ + +func restorev1beta1APIServerLoadBalancer(previous *infrav1.APIServerLoadBalancer, dst *infrav1.APIServerLoadBalancer) { + if dst == nil || previous == nil { + return + } + + // AZ doesn't exist in v1alpha6, so always restore. + dst.AvailabilityZone = previous.AvailabilityZone +} + +/* Placeholders */ + +// conversion-gen registers these functions so we must provider stubs, but +// nothing should ever call them + +func Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(_ *NetworkFilter, _ *infrav1.NetworkFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter should not be called") +} + +func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(_ *infrav1.NetworkFilter, _ *NetworkFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter should not be called") +} + +func Convert_v1alpha6_NetworkParam_To_v1beta1_NetworkParam(_ *NetworkParam, _ *infrav1.NetworkParam, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha6_NetworkParam_To_v1beta1_NetworkParam should not be called") +} + +func Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkParam(_ *infrav1.NetworkParam, _ *NetworkParam, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkParam should not be called") +} diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index 6bfa0129c3..59dba6198a 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,11 +24,13 @@ package v1alpha6 import ( unsafe "unsafe" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" - v1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" - v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" + v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" + apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" errors "sigs.k8s.io/cluster-api/errors" ) @@ -39,514 +41,559 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { - if err := s.AddGeneratedConversionFunc((*APIServerLoadBalancer)(nil), (*v1alpha7.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha7.APIServerLoadBalancer), scope) + if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1beta1.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_AddressPair_To_v1beta1_AddressPair(a.(*AddressPair), b.(*v1beta1.AddressPair), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(a.(*v1alpha7.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(a.(*v1beta1.AddressPair), b.(*AddressPair), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1alpha7.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_AddressPair_To_v1alpha7_AddressPair(a.(*AddressPair), b.(*v1alpha7.AddressPair), scope) + if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1beta1.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1beta1.ExternalRouterIPParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_AddressPair_To_v1alpha6_AddressPair(a.(*v1alpha7.AddressPair), b.(*AddressPair), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(a.(*v1beta1.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha7.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_Bastion_To_v1alpha7_Bastion(a.(*Bastion), b.(*v1alpha7.Bastion), scope) + if err := s.AddGeneratedConversionFunc((*FixedIP)(nil), (*v1beta1.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP(a.(*FixedIP), b.(*v1beta1.FixedIP), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_Bastion_To_v1alpha6_Bastion(a.(*v1alpha7.Bastion), b.(*Bastion), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_FixedIP_To_v1alpha6_FixedIP(a.(*v1beta1.FixedIP), b.(*FixedIP), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1alpha7.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha7.ExternalRouterIPParam), scope) + if err := s.AddGeneratedConversionFunc((*LoadBalancer)(nil), (*v1beta1.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_LoadBalancer_To_v1beta1_LoadBalancer(a.(*LoadBalancer), b.(*v1beta1.LoadBalancer), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(a.(*v1alpha7.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1beta1.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster(a.(*OpenStackCluster), b.(*v1beta1.OpenStackCluster), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*FixedIP)(nil), (*v1alpha7.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_FixedIP_To_v1alpha7_FixedIP(a.(*FixedIP), b.(*v1alpha7.FixedIP), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster(a.(*v1beta1.OpenStackCluster), b.(*OpenStackCluster), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_FixedIP_To_v1alpha6_FixedIP(a.(*v1alpha7.FixedIP), b.(*FixedIP), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterList)(nil), (*v1beta1.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1beta1.OpenStackClusterList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*LoadBalancer)(nil), (*v1alpha7.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_LoadBalancer_To_v1alpha7_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha7.LoadBalancer), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(a.(*v1beta1.OpenStackClusterList), b.(*OpenStackClusterList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer(a.(*v1alpha7.LoadBalancer), b.(*LoadBalancer), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1beta1.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1beta1.OpenStackClusterTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*NetworkFilter)(nil), (*v1alpha7.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha7.NetworkFilter), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(a.(*v1beta1.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(a.(*v1alpha7.NetworkFilter), b.(*NetworkFilter), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateList)(nil), (*v1beta1.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1beta1.OpenStackClusterTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1alpha7.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha7.OpenStackCluster), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(a.(*v1beta1.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster(a.(*v1alpha7.OpenStackCluster), b.(*OpenStackCluster), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateResource)(nil), (*v1beta1.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1beta1.OpenStackClusterTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterList)(nil), (*v1alpha7.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha7.OpenStackClusterList), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(a.(*v1beta1.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(a.(*v1alpha7.OpenStackClusterList), b.(*OpenStackClusterList), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateSpec)(nil), (*v1beta1.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1beta1.OpenStackClusterTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha7.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha7.OpenStackClusterSpec), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(a.(*v1beta1.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1alpha7.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha7.OpenStackClusterTemplate), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1beta1.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1beta1.OpenStackMachineList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(a.(*v1alpha7.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(a.(*v1beta1.OpenStackMachineList), b.(*OpenStackMachineList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateList)(nil), (*v1alpha7.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha7.OpenStackClusterTemplateList), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1beta1.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1beta1.OpenStackMachineStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(a.(*v1alpha7.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1beta1.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1beta1.OpenStackMachineTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateResource)(nil), (*v1alpha7.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha7.OpenStackClusterTemplateResource), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(a.(*v1beta1.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(a.(*v1alpha7.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1beta1.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1beta1.OpenStackMachineTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateSpec)(nil), (*v1alpha7.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha7.OpenStackClusterTemplateSpec), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(a.(*v1beta1.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(a.(*v1alpha7.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1beta1.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1beta1.OpenStackMachineTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha7.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha7.OpenStackIdentityReference), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(a.(*v1beta1.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(a.(*v1alpha7.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope) + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1beta1.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1beta1.OpenStackMachineTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1alpha7.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha7.OpenStackMachine), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(a.(*v1beta1.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine(a.(*v1alpha7.OpenStackMachine), b.(*OpenStackMachine), scope) + if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1beta1.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_Router_To_v1beta1_Router(a.(*Router), b.(*v1beta1.Router), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1alpha7.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha7.OpenStackMachineList), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Router_To_v1alpha6_Router(a.(*v1beta1.Router), b.(*Router), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(a.(*v1alpha7.OpenStackMachineList), b.(*OpenStackMachineList), scope) + if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1beta1.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_Subnet_To_v1beta1_Subnet(a.(*Subnet), b.(*v1beta1.Subnet), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1alpha7.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha7.OpenStackMachineStatus), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Subnet_To_v1alpha6_Subnet(a.(*v1beta1.Subnet), b.(*Subnet), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(a.(*v1alpha7.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope) + if err := s.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1beta1.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_ValueSpec_To_v1beta1_ValueSpec(a.(*ValueSpec), b.(*v1beta1.ValueSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1alpha7.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha7.OpenStackMachineTemplate), scope) + if err := s.AddGeneratedConversionFunc((*v1beta1.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ValueSpec_To_v1alpha6_ValueSpec(a.(*v1beta1.ValueSpec), b.(*ValueSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(a.(*v1alpha7.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope) + if err := s.AddConversionFunc((*APIServerLoadBalancer)(nil), (*v1beta1.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1beta1.APIServerLoadBalancer), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1alpha7.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha7.OpenStackMachineTemplateList), scope) + if err := s.AddConversionFunc((*Bastion)(nil), (*v1beta1.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_Bastion_To_v1beta1_Bastion(a.(*Bastion), b.(*v1beta1.Bastion), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(a.(*v1alpha7.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope) + if err := s.AddConversionFunc((*Instance)(nil), (*v1beta1.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_Instance_To_v1beta1_BastionStatus(a.(*Instance), b.(*v1beta1.BastionStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1alpha7.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha7.OpenStackMachineTemplateResource), scope) + if err := s.AddConversionFunc((*NetworkFilter)(nil), (*v1beta1.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(a.(*NetworkFilter), b.(*v1beta1.NetworkFilter), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(a.(*v1alpha7.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope) + if err := s.AddConversionFunc((*NetworkFilter)(nil), (*v1beta1.NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(a.(*NetworkFilter), b.(*v1beta1.NetworkParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1alpha7.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha7.OpenStackMachineTemplateSpec), scope) + if err := s.AddConversionFunc((*NetworkParam)(nil), (*v1beta1.NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_NetworkParam_To_v1beta1_NetworkParam(a.(*NetworkParam), b.(*v1beta1.NetworkParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(a.(*v1alpha7.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope) + if err := s.AddConversionFunc((*Network)(nil), (*v1beta1.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_Network_To_v1beta1_NetworkStatus(a.(*Network), b.(*v1beta1.NetworkStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha7.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(a.(*RootVolume), b.(*v1alpha7.RootVolume), scope) + if err := s.AddConversionFunc((*Network)(nil), (*v1beta1.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_Network_To_v1beta1_NetworkStatusWithSubnets(a.(*Network), b.(*v1beta1.NetworkStatusWithSubnets), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(a.(*v1alpha7.RootVolume), b.(*RootVolume), scope) + if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1beta1.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1beta1.OpenStackClusterSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha7.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_Router_To_v1alpha7_Router(a.(*Router), b.(*v1alpha7.Router), scope) + if err := s.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1beta1.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1beta1.OpenStackClusterStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_Router_To_v1alpha6_Router(a.(*v1alpha7.Router), b.(*Router), scope) + if err := s.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1beta1.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1beta1.OpenStackIdentityReference), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha7.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SecurityGroup_To_v1alpha7_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha7.SecurityGroup), scope) + if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1beta1.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1beta1.OpenStackMachineSpec), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroup_To_v1alpha6_SecurityGroup(a.(*v1alpha7.SecurityGroup), b.(*SecurityGroup), scope) + if err := s.AddConversionFunc((*OpenStackMachine)(nil), (*v1beta1.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(a.(*OpenStackMachine), b.(*v1beta1.OpenStackMachine), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1alpha7.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*PortOpts)(nil), (*v1beta1.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(a.(*PortOpts), b.(*v1beta1.PortOpts), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha7.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha7.SecurityGroupRule), scope) + if err := s.AddConversionFunc((*RootVolume)(nil), (*v1beta1.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_RootVolume_To_v1beta1_RootVolume(a.(*RootVolume), b.(*v1beta1.RootVolume), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(a.(*v1alpha7.SecurityGroupRule), b.(*SecurityGroupRule), scope) + if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1beta1.SecurityGroupFilter), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha7.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_Subnet_To_v1alpha7_Subnet(a.(*Subnet), b.(*v1alpha7.Subnet), scope) + if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_Subnet_To_v1alpha6_Subnet(a.(*v1alpha7.Subnet), b.(*Subnet), scope) + if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1beta1.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1beta1.SecurityGroupStatus), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*SubnetFilter)(nil), (*v1alpha7.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha7.SubnetFilter), scope) + if err := s.AddConversionFunc((*SubnetFilter)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(a.(*SubnetFilter), b.(*v1beta1.SubnetFilter), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(a.(*v1alpha7.SubnetFilter), b.(*SubnetFilter), scope) + if err := s.AddConversionFunc((*SubnetFilter)(nil), (*v1beta1.SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(a.(*SubnetFilter), b.(*v1beta1.SubnetParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1alpha7.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_ValueSpec_To_v1alpha7_ValueSpec(a.(*ValueSpec), b.(*v1alpha7.ValueSpec), scope) + if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetParam(a.(*SubnetParam), b.(*v1beta1.SubnetParam), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1alpha7.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_ValueSpec_To_v1alpha6_ValueSpec(a.(*v1alpha7.ValueSpec), b.(*ValueSpec), scope) + if err := s.AddConversionFunc((*v1beta1.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(a.(*v1beta1.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*Instance)(nil), (*v1alpha7.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_Instance_To_v1alpha7_BastionStatus(a.(*Instance), b.(*v1alpha7.BastionStatus), scope) + if err := s.AddConversionFunc((*v1beta1.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_BastionStatus_To_v1alpha6_Instance(a.(*v1beta1.BastionStatus), b.(*Instance), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*Network)(nil), (*v1alpha7.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_Network_To_v1alpha7_NetworkStatus(a.(*Network), b.(*v1alpha7.NetworkStatus), scope) + if err := s.AddConversionFunc((*v1beta1.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Bastion_To_v1alpha6_Bastion(a.(*v1beta1.Bastion), b.(*Bastion), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*Network)(nil), (*v1alpha7.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_Network_To_v1alpha7_NetworkStatusWithSubnets(a.(*Network), b.(*v1alpha7.NetworkStatusWithSubnets), scope) + if err := s.AddConversionFunc((*v1beta1.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(a.(*v1beta1.LoadBalancer), b.(*LoadBalancer), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha7.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha7.OpenStackClusterStatus), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(a.(*v1beta1.NetworkFilter), b.(*NetworkFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha7.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha7.OpenStackMachineSpec), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkParam)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkFilter(a.(*v1beta1.NetworkParam), b.(*NetworkFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*PortOpts)(nil), (*v1alpha7.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(a.(*PortOpts), b.(*v1alpha7.PortOpts), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkParam)(nil), (*NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkParam(a.(*v1beta1.NetworkParam), b.(*NetworkParam), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha7.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha7.SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha6_Network(a.(*v1beta1.NetworkStatusWithSubnets), b.(*Network), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1alpha7.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1alpha7.SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*v1beta1.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkStatus_To_v1alpha6_Network(a.(*v1beta1.NetworkStatus), b.(*Network), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1alpha7.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SubnetParam_To_v1alpha7_SubnetFilter(a.(*SubnetParam), b.(*v1alpha7.SubnetFilter), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(a.(*v1beta1.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_BastionStatus_To_v1alpha6_Instance(a.(*v1alpha7.BastionStatus), b.(*Instance), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(a.(*v1beta1.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha6_Network(a.(*v1alpha7.NetworkStatusWithSubnets), b.(*Network), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(a.(*v1beta1.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_NetworkStatus_To_v1alpha6_Network(a.(*v1alpha7.NetworkStatus), b.(*Network), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(a.(*v1beta1.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(a.(*v1alpha7.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(a.(*v1beta1.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(a.(*v1alpha7.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope) + if err := s.AddConversionFunc((*v1beta1.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(a.(*v1beta1.OpenStackMachine), b.(*OpenStackMachine), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(a.(*v1alpha7.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope) + if err := s.AddConversionFunc((*v1beta1.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(a.(*v1beta1.PortOpts), b.(*PortOpts), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(a.(*v1alpha7.PortOpts), b.(*PortOpts), scope) + if err := s.AddConversionFunc((*v1beta1.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RootVolume_To_v1alpha6_RootVolume(a.(*v1beta1.RootVolume), b.(*RootVolume), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1alpha7.SecurityGroupFilter), b.(*SecurityGroupParam), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1alpha7.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1alpha7.SubnetFilter), b.(*SubnetParam), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*string)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_string(a.(*v1beta1.SecurityGroupParam), b.(*string), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupParam), b.(*SecurityGroupParam), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(a.(*v1beta1.SecurityGroupStatus), b.(*SecurityGroup), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(a.(*v1beta1.SubnetFilter), b.(*SubnetFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetParam)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetFilter(a.(*v1beta1.SubnetParam), b.(*SubnetFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetParam)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetParam(a.(*v1beta1.SubnetParam), b.(*SubnetParam), scope) }); err != nil { return err } return nil } -func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha7.APIServerLoadBalancer, s conversion.Scope) error { - out.Enabled = in.Enabled +func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts)) out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) - out.Provider = in.Provider + if err := optional.Convert_string_To_optional_String(&in.Provider, &out.Provider, s); err != nil { + return err + } return nil } -// Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer is an autogenerated conversion function. -func Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha7.APIServerLoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s) -} - -func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha7.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { - out.Enabled = in.Enabled +func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts)) out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) - out.Provider = in.Provider + if err := optional.Convert_optional_String_To_string(&in.Provider, &out.Provider, s); err != nil { + return err + } + // WARNING: in.Network requires manual conversion: does not exist in peer-type + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer is an autogenerated conversion function. -func Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha7.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in, out, s) -} - -func autoConvert_v1alpha6_AddressPair_To_v1alpha7_AddressPair(in *AddressPair, out *v1alpha7.AddressPair, s conversion.Scope) error { +func autoConvert_v1alpha6_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error { out.IPAddress = in.IPAddress - out.MACAddress = in.MACAddress + if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha6_AddressPair_To_v1alpha7_AddressPair is an autogenerated conversion function. -func Convert_v1alpha6_AddressPair_To_v1alpha7_AddressPair(in *AddressPair, out *v1alpha7.AddressPair, s conversion.Scope) error { - return autoConvert_v1alpha6_AddressPair_To_v1alpha7_AddressPair(in, out, s) +// Convert_v1alpha6_AddressPair_To_v1beta1_AddressPair is an autogenerated conversion function. +func Convert_v1alpha6_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error { + return autoConvert_v1alpha6_AddressPair_To_v1beta1_AddressPair(in, out, s) } -func autoConvert_v1alpha7_AddressPair_To_v1alpha6_AddressPair(in *v1alpha7.AddressPair, out *AddressPair, s conversion.Scope) error { +func autoConvert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error { out.IPAddress = in.IPAddress - out.MACAddress = in.MACAddress + if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha7_AddressPair_To_v1alpha6_AddressPair is an autogenerated conversion function. -func Convert_v1alpha7_AddressPair_To_v1alpha6_AddressPair(in *v1alpha7.AddressPair, out *AddressPair, s conversion.Scope) error { - return autoConvert_v1alpha7_AddressPair_To_v1alpha6_AddressPair(in, out, s) +// Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair is an autogenerated conversion function. +func Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error { + return autoConvert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in, out, s) } -func autoConvert_v1alpha6_Bastion_To_v1alpha7_Bastion(in *Bastion, out *v1alpha7.Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled - if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil { +func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error { + if err := optional.Convert_bool_To_optional_Bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + // WARNING: in.Instance requires manual conversion: does not exist in peer-type + if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { return err } - out.AvailabilityZone = in.AvailabilityZone return nil } -// Convert_v1alpha6_Bastion_To_v1alpha7_Bastion is an autogenerated conversion function. -func Convert_v1alpha6_Bastion_To_v1alpha7_Bastion(in *Bastion, out *v1alpha7.Bastion, s conversion.Scope) error { - return autoConvert_v1alpha6_Bastion_To_v1alpha7_Bastion(in, out, s) -} - -func autoConvert_v1alpha7_Bastion_To_v1alpha6_Bastion(in *v1alpha7.Bastion, out *Bastion, s conversion.Scope) error { - out.Enabled = in.Enabled - if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil { +func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error { + if err := optional.Convert_optional_Bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { return err } - out.AvailabilityZone = in.AvailabilityZone + // WARNING: in.Spec requires manual conversion: does not exist in peer-type + if err := optional.Convert_optional_String_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { + return err + } + // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_Bastion_To_v1alpha6_Bastion is an autogenerated conversion function. -func Convert_v1alpha7_Bastion_To_v1alpha6_Bastion(in *v1alpha7.Bastion, out *Bastion, s conversion.Scope) error { - return autoConvert_v1alpha7_Bastion_To_v1alpha6_Bastion(in, out, s) -} - -func autoConvert_v1alpha6_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha7.ExternalRouterIPParam, s conversion.Scope) error { +func autoConvert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1beta1.ExternalRouterIPParam, s conversion.Scope) error { out.FixedIP = in.FixedIP - if err := Convert_v1alpha6_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { + if err := Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { return err } return nil } -// Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam is an autogenerated conversion function. -func Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha7.ExternalRouterIPParam, s conversion.Scope) error { - return autoConvert_v1alpha6_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in, out, s) +// Convert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam is an autogenerated conversion function. +func Convert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1beta1.ExternalRouterIPParam, s conversion.Scope) error { + return autoConvert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in, out, s) } -func autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha7.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { +func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { out.FixedIP = in.FixedIP - if err := Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { + if err := Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { return err } return nil } -// Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam is an autogenerated conversion function. -func Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha7.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { - return autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in, out, s) +// Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam is an autogenerated conversion function. +func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { + return autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in, out, s) } -func autoConvert_v1alpha6_FixedIP_To_v1alpha7_FixedIP(in *FixedIP, out *v1alpha7.FixedIP, s conversion.Scope) error { - out.Subnet = (*v1alpha7.SubnetFilter)(unsafe.Pointer(in.Subnet)) - out.IPAddress = in.IPAddress +func autoConvert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error { + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(v1beta1.SubnetParam) + if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(*in, *out, s); err != nil { + return err + } + } else { + out.Subnet = nil + } + if err := optional.Convert_string_To_optional_String(&in.IPAddress, &out.IPAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha6_FixedIP_To_v1alpha7_FixedIP is an autogenerated conversion function. -func Convert_v1alpha6_FixedIP_To_v1alpha7_FixedIP(in *FixedIP, out *v1alpha7.FixedIP, s conversion.Scope) error { - return autoConvert_v1alpha6_FixedIP_To_v1alpha7_FixedIP(in, out, s) +// Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP is an autogenerated conversion function. +func Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error { + return autoConvert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in, out, s) } -func autoConvert_v1alpha7_FixedIP_To_v1alpha6_FixedIP(in *v1alpha7.FixedIP, out *FixedIP, s conversion.Scope) error { - out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet)) - out.IPAddress = in.IPAddress +func autoConvert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error { + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(SubnetFilter) + if err := Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Subnet = nil + } + if err := optional.Convert_optional_String_To_string(&in.IPAddress, &out.IPAddress, s); err != nil { + return err + } return nil } -// Convert_v1alpha7_FixedIP_To_v1alpha6_FixedIP is an autogenerated conversion function. -func Convert_v1alpha7_FixedIP_To_v1alpha6_FixedIP(in *v1alpha7.FixedIP, out *FixedIP, s conversion.Scope) error { - return autoConvert_v1alpha7_FixedIP_To_v1alpha6_FixedIP(in, out, s) +// Convert_v1beta1_FixedIP_To_v1alpha6_FixedIP is an autogenerated conversion function. +func Convert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error { + return autoConvert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in, out, s) } -func autoConvert_v1alpha6_LoadBalancer_To_v1alpha7_LoadBalancer(in *LoadBalancer, out *v1alpha7.LoadBalancer, s conversion.Scope) error { +func autoConvert_v1alpha6_LoadBalancer_To_v1beta1_LoadBalancer(in *LoadBalancer, out *v1beta1.LoadBalancer, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.IP = in.IP @@ -556,99 +603,95 @@ func autoConvert_v1alpha6_LoadBalancer_To_v1alpha7_LoadBalancer(in *LoadBalancer return nil } -// Convert_v1alpha6_LoadBalancer_To_v1alpha7_LoadBalancer is an autogenerated conversion function. -func Convert_v1alpha6_LoadBalancer_To_v1alpha7_LoadBalancer(in *LoadBalancer, out *v1alpha7.LoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha6_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s) +// Convert_v1alpha6_LoadBalancer_To_v1beta1_LoadBalancer is an autogenerated conversion function. +func Convert_v1alpha6_LoadBalancer_To_v1beta1_LoadBalancer(in *LoadBalancer, out *v1beta1.LoadBalancer, s conversion.Scope) error { + return autoConvert_v1alpha6_LoadBalancer_To_v1beta1_LoadBalancer(in, out, s) } -func autoConvert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha7.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { +func autoConvert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.IP = in.IP out.InternalIP = in.InternalIP out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.LoadBalancerNetwork requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer is an autogenerated conversion function. -func Convert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha7.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { - return autoConvert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer(in, out, s) -} - -func autoConvert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFilter, out *v1alpha7.NetworkFilter, s conversion.Scope) error { +func autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter is an autogenerated conversion function. -func Convert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFilter, out *v1alpha7.NetworkFilter, s conversion.Scope) error { - return autoConvert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s) -} - -func autoConvert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha7.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { +func autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter is an autogenerated conversion function. -func Convert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha7.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { - return autoConvert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s) +func autoConvert_v1alpha6_NetworkParam_To_v1beta1_NetworkParam(in *NetworkParam, out *v1beta1.NetworkParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.FixedIP requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.NetworkFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter) + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_NetworkParam_To_v1alpha6_NetworkParam(in *v1beta1.NetworkParam, out *NetworkParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.NetworkFilter) + return nil } -func autoConvert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *OpenStackCluster, out *v1alpha7.OpenStackCluster, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *OpenStackCluster, out *v1alpha7.OpenStackCluster, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster(in, out, s) +// Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster(in, out, s) } -func autoConvert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha7.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha7.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster(in, out, s) +// Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster is an autogenerated conversion function. +func Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster(in, out, s) } -func autoConvert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha7.OpenStackClusterList, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in *OpenStackClusterList, out *v1beta1.OpenStackClusterList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackCluster, len(*in)) + *out = make([]v1beta1.OpenStackCluster, len(*in)) for i := range *in { - if err := Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -658,18 +701,18 @@ func autoConvert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList( return nil } -// Convert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha7.OpenStackClusterList, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in, out, s) +// Convert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in *OpenStackClusterList, out *v1beta1.OpenStackClusterList, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha7.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1beta1.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackCluster, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -679,122 +722,127 @@ func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList( return nil } -// Convert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha7.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in, out, s) +// Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1beta1.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in, out, s) } -func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha7.OpenStackClusterSpec, s conversion.Scope) error { - out.CloudName = in.CloudName - out.NodeCIDR = in.NodeCIDR - if err := Convert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil { - return err - } - if err := Convert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } - out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) +func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error { + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type + // WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type + // WARNING: in.Network requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.NetworkFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam) + // WARNING: in.Subnet requires manual conversion: does not exist in peer-type + // WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs - *out = make([]v1alpha7.ExternalRouterIPParam, len(*in)) + *out = make([]v1beta1.ExternalRouterIPParam, len(*in)) for i := range *in { - if err := Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { out.ExternalRouterIPs = nil } - out.ExternalNetworkID = in.ExternalNetworkID - if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + // WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type + // WARNING: in.APIServerLoadBalancer requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.APIServerLoadBalancer vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.APIServerLoadBalancer) + if err := optional.Convert_bool_To_optional_Bool(&in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.APIServerFloatingIP, &out.APIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.APIServerFixedIP, &out.APIServerFixedIP, s); err != nil { + return err + } + if err := optional.Convert_int_To_optional_Int(&in.APIServerPort, &out.APIServerPort, s); err != nil { + return err + } + // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups) + // WARNING: in.AllowAllInClusterTraffic requires manual conversion: does not exist in peer-type + if err := optional.Convert_bool_To_optional_Bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil { return err } - out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP - out.APIServerFloatingIP = in.APIServerFloatingIP - out.APIServerFixedIP = in.APIServerFixedIP - out.APIServerPort = in.APIServerPort - out.ManagedSecurityGroups = in.ManagedSecurityGroups - out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic - out.DisablePortSecurity = in.DisablePortSecurity out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + // WARNING: in.ControlPlaneEndpoint requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint vs *sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint) out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones)) - out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone + if err := optional.Convert_bool_To_optional_Bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil { + return err + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion - *out = new(v1alpha7.Bastion) - if err := Convert_v1alpha6_Bastion_To_v1alpha7_Bastion(*in, *out, s); err != nil { + *out = new(v1beta1.Bastion) + if err := Convert_v1alpha6_Bastion_To_v1beta1_Bastion(*in, *out, s); err != nil { return err } } else { out.Bastion = nil } - out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + // WARNING: in.IdentityRef requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.OpenStackIdentityReference vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference) return nil } -// Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha7.OpenStackClusterSpec, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s) -} - -func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha7.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { - out.CloudName = in.CloudName - out.NodeCIDR = in.NodeCIDR +func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { + // WARNING: in.ManagedSubnets requires manual conversion: does not exist in peer-type // WARNING: in.Router requires manual conversion: does not exist in peer-type - if err := Convert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil { - return err - } - if err := Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Network requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.NetworkFilter) + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type // WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type - out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs *out = make([]ExternalRouterIPParam, len(*in)) for i := range *in { - if err := Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { out.ExternalRouterIPs = nil } - out.ExternalNetworkID = in.ExternalNetworkID - if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + // WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type + // WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type + // WARNING: in.APIServerLoadBalancer requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.APIServerLoadBalancer vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.APIServerLoadBalancer) + if err := optional.Convert_optional_Bool_To_bool(&in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.APIServerFloatingIP, &out.APIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.APIServerFixedIP, &out.APIServerFixedIP, s); err != nil { + return err + } + if err := optional.Convert_optional_Int_To_int(&in.APIServerPort, &out.APIServerPort, s); err != nil { + return err + } + // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool) + if err := optional.Convert_optional_Bool_To_bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil { return err } - out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP - out.APIServerFloatingIP = in.APIServerFloatingIP - out.APIServerFixedIP = in.APIServerFixedIP - out.APIServerPort = in.APIServerPort - out.ManagedSecurityGroups = in.ManagedSecurityGroups - out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic - out.DisablePortSecurity = in.DisablePortSecurity out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + // WARNING: in.ControlPlaneEndpoint requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint vs sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint) out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones)) - out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone + if err := optional.Convert_optional_Bool_To_bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil { + return err + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion *out = new(Bastion) - if err := Convert_v1alpha7_Bastion_To_v1alpha6_Bastion(*in, *out, s); err != nil { + if err := Convert_v1beta1_Bastion_To_v1alpha6_Bastion(*in, *out, s); err != nil { return err } } else { out.Bastion = nil } - out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + // WARNING: in.IdentityRef requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.OpenStackIdentityReference) return nil } -func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha7.OpenStackClusterStatus, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1beta1.OpenStackClusterStatus, s conversion.Scope) error { out.Ready = in.Ready if in.Network != nil { in, out := &in.Network, &out.Network - *out = new(v1alpha7.NetworkStatusWithSubnets) - if err := Convert_v1alpha6_Network_To_v1alpha7_NetworkStatusWithSubnets(*in, *out, s); err != nil { + *out = new(v1beta1.NetworkStatusWithSubnets) + if err := Convert_v1alpha6_Network_To_v1beta1_NetworkStatusWithSubnets(*in, *out, s); err != nil { return err } } else { @@ -802,21 +850,45 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta } if in.ExternalNetwork != nil { in, out := &in.ExternalNetwork, &out.ExternalNetwork - *out = new(v1alpha7.NetworkStatus) - if err := Convert_v1alpha6_Network_To_v1alpha7_NetworkStatus(*in, *out, s); err != nil { + *out = new(v1beta1.NetworkStatus) + if err := Convert_v1alpha6_Network_To_v1beta1_NetworkStatus(*in, *out, s); err != nil { return err } } else { out.ExternalNetwork = nil } - out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) - out.ControlPlaneSecurityGroup = (*v1alpha7.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup)) - out.WorkerSecurityGroup = (*v1alpha7.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup)) - out.BastionSecurityGroup = (*v1alpha7.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup)) + out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) + if in.ControlPlaneSecurityGroup != nil { + in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.ControlPlaneSecurityGroup = nil + } + if in.WorkerSecurityGroup != nil { + in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.WorkerSecurityGroup = nil + } + if in.BastionSecurityGroup != nil { + in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.BastionSecurityGroup = nil + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion - *out = new(v1alpha7.BastionStatus) - if err := Convert_v1alpha6_Instance_To_v1alpha7_BastionStatus(*in, *out, s); err != nil { + *out = new(v1beta1.BastionStatus) + if err := Convert_v1alpha6_Instance_To_v1beta1_BastionStatus(*in, *out, s); err != nil { return err } } else { @@ -827,12 +899,12 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta return nil } -func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *v1alpha7.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *v1beta1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { out.Ready = in.Ready if in.Network != nil { in, out := &in.Network, &out.Network *out = new(Network) - if err := Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha6_Network(*in, *out, s); err != nil { + if err := Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha6_Network(*in, *out, s); err != nil { return err } } else { @@ -841,7 +913,7 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta if in.ExternalNetwork != nil { in, out := &in.ExternalNetwork, &out.ExternalNetwork *out = new(Network) - if err := Convert_v1alpha7_NetworkStatus_To_v1alpha6_Network(*in, *out, s); err != nil { + if err := Convert_v1beta1_NetworkStatus_To_v1alpha6_Network(*in, *out, s); err != nil { return err } } else { @@ -849,14 +921,38 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta } // WARNING: in.Router requires manual conversion: does not exist in peer-type // WARNING: in.APIServerLoadBalancer requires manual conversion: does not exist in peer-type - out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) - out.ControlPlaneSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup)) - out.WorkerSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup)) - out.BastionSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup)) + out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) + if in.ControlPlaneSecurityGroup != nil { + in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.ControlPlaneSecurityGroup = nil + } + if in.WorkerSecurityGroup != nil { + in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.WorkerSecurityGroup = nil + } + if in.BastionSecurityGroup != nil { + in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.BastionSecurityGroup = nil + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion *out = new(Instance) - if err := Convert_v1alpha7_BastionStatus_To_v1alpha6_Instance(*in, *out, s); err != nil { + if err := Convert_v1beta1_BastionStatus_To_v1alpha6_Instance(*in, *out, s); err != nil { return err } } else { @@ -867,39 +963,39 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta return nil } -func autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha7.OpenStackClusterTemplate, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1beta1.OpenStackClusterTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha7.OpenStackClusterTemplate, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in, out, s) +// Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1beta1.OpenStackClusterTemplate, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha7.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha7.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in, out, s) } -func autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha7.OpenStackClusterTemplateList, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1beta1.OpenStackClusterTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackClusterTemplate, len(*in)) + *out = make([]v1beta1.OpenStackClusterTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -909,18 +1005,18 @@ func autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClus return nil } -// Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha7.OpenStackClusterTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in, out, s) +// Convert_v1alpha6_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1beta1.OpenStackClusterTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha7.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1beta1.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackClusterTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -930,120 +1026,100 @@ func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClus return nil } -// Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha7.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1beta1.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in, out, s) } -func autoConvert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha7.OpenStackClusterTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1alpha6_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1beta1.OpenStackClusterTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha7.OpenStackClusterTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in, out, s) +// Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1beta1.OpenStackClusterTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1alpha7.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1beta1.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1alpha7.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1beta1.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in, out, s) } -func autoConvert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha7.OpenStackClusterTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1beta1.OpenStackClusterTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha7.OpenStackClusterTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in, out, s) +// Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1beta1.OpenStackClusterTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in, out, s) } -func autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1alpha7.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1beta1.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1alpha7.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in, out, s) +// Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1beta1.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in, out, s) } -func autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha7.OpenStackIdentityReference, s conversion.Scope) error { - out.Kind = in.Kind +func autoConvert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1beta1.OpenStackIdentityReference, s conversion.Scope) error { + // WARNING: in.Kind requires manual conversion: does not exist in peer-type out.Name = in.Name return nil } -// Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha7.OpenStackIdentityReference, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in, out, s) -} - -func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha7.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { - out.Kind = in.Kind +func autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { out.Name = in.Name + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha7.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in, out, s) -} - -func autoConvert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *OpenStackMachine, out *v1alpha7.OpenStackMachine, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *OpenStackMachine, out *v1alpha7.OpenStackMachine, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s) -} - -func autoConvert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha7.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } - if err := Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { + if err := Convert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha7.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine(in, out, s) -} - -func autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha7.OpenStackMachineList, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackMachine, len(*in)) + *out = make([]v1beta1.OpenStackMachine, len(*in)) for i := range *in { - if err := Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1053,18 +1129,18 @@ func autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList( return nil } -// Convert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha7.OpenStackMachineList, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in, out, s) +// Convert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha7.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1beta1.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackMachine, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1074,25 +1150,25 @@ func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList( return nil } -// Convert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha7.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in, out, s) +// Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1beta1.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in, out, s) } -func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha7.OpenStackMachineSpec, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1beta1.OpenStackMachineSpec, s conversion.Scope) error { out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) - out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) - out.CloudName = in.CloudName + // WARNING: in.InstanceID requires manual conversion: does not exist in peer-type + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type out.Flavor = in.Flavor - out.Image = in.Image - out.ImageUUID = in.ImageUUID + // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam) + // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type out.SSHKeyName = in.SSHKeyName // WARNING: in.Networks requires manual conversion: does not exist in peer-type if in.Ports != nil { in, out := &in.Ports, &out.Ports - *out = make([]v1alpha7.PortOpts, len(*in)) + *out = make([]v1beta1.PortOpts, len(*in)) for i := range *in { - if err := Convert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1100,12 +1176,12 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec( out.Ports = nil } // WARNING: in.Subnet requires manual conversion: does not exist in peer-type - out.FloatingIP = in.FloatingIP + // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]v1alpha7.SecurityGroupFilter, len(*in)) + *out = make([]v1beta1.SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha6_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1114,39 +1190,51 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec( } out.Trunk = in.Trunk out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) + // WARNING: in.ServerMetadata requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*v1alpha7.RootVolume)(unsafe.Pointer(in.RootVolume)) - out.ServerGroupID = in.ServerGroupID - out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(v1beta1.RootVolume) + if err := Convert_v1alpha6_RootVolume_To_v1beta1_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } + // WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(v1beta1.OpenStackIdentityReference) + if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil { + return err + } + } else { + out.IdentityRef = nil + } return nil } -func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *v1alpha7.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *v1beta1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) - out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) - out.CloudName = in.CloudName out.Flavor = in.Flavor - out.Image = in.Image - out.ImageUUID = in.ImageUUID + // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam vs string) out.SSHKeyName = in.SSHKeyName if in.Ports != nil { in, out := &in.Ports, &out.Ports *out = make([]PortOpts, len(*in)) for i := range *in { - if err := Convert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { out.Ports = nil } - out.FloatingIP = in.FloatingIP if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1155,78 +1243,93 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec( } out.Trunk = in.Trunk out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) + // WARNING: in.ServerMetadata requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata vs map[string]string) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + if err := Convert_v1beta1_RootVolume_To_v1alpha6_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } // WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type - out.ServerGroupID = in.ServerGroupID - out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) + // WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(OpenStackIdentityReference) + if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil { + return err + } + } else { + out.IdentityRef = nil + } + // WARNING: in.FloatingIPPoolRef requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha7.OpenStackMachineStatus, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1beta1.OpenStackMachineStatus, s conversion.Scope) error { out.Ready = in.Ready - out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) - out.InstanceState = (*v1alpha7.InstanceState)(unsafe.Pointer(in.InstanceState)) + out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.InstanceState = (*v1beta1.InstanceState)(unsafe.Pointer(in.InstanceState)) out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) - out.Conditions = *(*v1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) + out.Conditions = *(*apiv1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) return nil } -// Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha7.OpenStackMachineStatus, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s) +// Convert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1beta1.OpenStackMachineStatus, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha7.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1beta1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { out.Ready = in.Ready - out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + // WARNING: in.InstanceID requires manual conversion: does not exist in peer-type + out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses)) out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState)) + // WARNING: in.Resolved requires manual conversion: does not exist in peer-type + // WARNING: in.Resources requires manual conversion: does not exist in peer-type out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) - out.Conditions = *(*v1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) + out.Conditions = *(*apiv1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) return nil } -// Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha7.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s) -} - -func autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha7.OpenStackMachineTemplate, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1beta1.OpenStackMachineTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha7.OpenStackMachineTemplate, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in, out, s) +// Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1beta1.OpenStackMachineTemplate, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha7.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha7.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in, out, s) } -func autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha7.OpenStackMachineTemplateList, s conversion.Scope) error { +func autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1beta1.OpenStackMachineTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]v1alpha7.OpenStackMachineTemplate, len(*in)) + *out = make([]v1beta1.OpenStackMachineTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1236,18 +1339,18 @@ func autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMach return nil } -// Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha7.OpenStackMachineTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in, out, s) +// Convert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1beta1.OpenStackMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha7.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { +func autoConvert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1beta1.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]OpenStackMachineTemplate, len(*in)) for i := range *in { - if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1257,146 +1360,161 @@ func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMach return nil } -// Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha7.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1beta1.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in, out, s) } -func autoConvert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha7.OpenStackMachineTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1alpha6_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1beta1.OpenStackMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha7.OpenStackMachineTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in, out, s) +// Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1beta1.OpenStackMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1alpha7.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { +func autoConvert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1beta1.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1alpha7.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1beta1.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in, out, s) } -func autoConvert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha7.OpenStackMachineTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1beta1.OpenStackMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha7.OpenStackMachineTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in, out, s) +// Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1beta1.OpenStackMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha6_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in, out, s) } -func autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1alpha7.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { - if err := Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { +func autoConvert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1beta1.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { return err } return nil } -// Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1alpha7.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in, out, s) +// Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1beta1.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in, out, s) } -func autoConvert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *v1alpha7.PortOpts, s conversion.Scope) error { - out.Network = (*v1alpha7.NetworkFilter)(unsafe.Pointer(in.Network)) - out.NameSuffix = in.NameSuffix - out.Description = in.Description - out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp)) - out.MACAddress = in.MACAddress - out.FixedIPs = *(*[]v1alpha7.FixedIP)(unsafe.Pointer(&in.FixedIPs)) - // WARNING: in.TenantID requires manual conversion: does not exist in peer-type - // WARNING: in.ProjectID requires manual conversion: does not exist in peer-type - // WARNING: in.SecurityGroups requires manual conversion: does not exist in peer-type - if in.SecurityGroupFilters != nil { - in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters - *out = make([]v1alpha7.SecurityGroupFilter, len(*in)) +func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error { + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(v1beta1.NetworkParam) + if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(*in, *out, s); err != nil { + return err + } + } else { + out.Network = nil + } + if err := optional.Convert_string_To_optional_String(&in.NameSuffix, &out.NameSuffix, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.Description, &out.Description, s); err != nil { + return err + } + // WARNING: in.AdminStateUp requires manual conversion: does not exist in peer-type + // WARNING: in.MACAddress requires manual conversion: does not exist in peer-type + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]v1beta1.FixedIP, len(*in)) for i := range *in { - if err := Convert_v1alpha6_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { - out.SecurityGroupFilters = nil + out.FixedIPs = nil } - out.AllowedAddressPairs = *(*[]v1alpha7.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs)) + // WARNING: in.TenantID requires manual conversion: does not exist in peer-type + // WARNING: in.ProjectID requires manual conversion: does not exist in peer-type + // INFO: in.SecurityGroups opted out of conversion generation + // INFO: in.SecurityGroupFilters opted out of conversion generation + // WARNING: in.AllowedAddressPairs requires manual conversion: does not exist in peer-type out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) - out.HostID = in.HostID - out.VNICType = in.VNICType - // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile) - out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity)) + // WARNING: in.HostID requires manual conversion: does not exist in peer-type + // WARNING: in.VNICType requires manual conversion: does not exist in peer-type + // WARNING: in.Profile requires manual conversion: does not exist in peer-type + // WARNING: in.DisablePortSecurity requires manual conversion: does not exist in peer-type out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ValueSpecs = *(*[]v1alpha7.ValueSpec)(unsafe.Pointer(&in.ValueSpecs)) + // WARNING: in.ValueSpecs requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *v1alpha7.PortOpts, out *PortOpts, s conversion.Scope) error { - out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network)) - out.NameSuffix = in.NameSuffix - out.Description = in.Description - out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp)) - out.MACAddress = in.MACAddress - out.FixedIPs = *(*[]FixedIP)(unsafe.Pointer(&in.FixedIPs)) - if in.SecurityGroupFilters != nil { - in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters - *out = make([]SecurityGroupParam, len(*in)) +func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error { + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkFilter) + if err := Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Network = nil + } + if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil { + return err + } + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]FixedIP, len(*in)) for i := range *in { - if err := Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_FixedIP_To_v1alpha6_FixedIP(&(*in)[i], &(*out)[i], s); err != nil { return err } } } else { - out.SecurityGroupFilters = nil + out.FixedIPs = nil + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]string, len(*in)) + for i := range *in { + if err := Convert_v1beta1_SecurityGroupParam_To_string(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.SecurityGroups = nil } - out.AllowedAddressPairs = *(*[]AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs)) - out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) - out.HostID = in.HostID - out.VNICType = in.VNICType - // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile vs map[string]string) - out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity)) - // WARNING: in.PropagateUplinkStatus requires manual conversion: does not exist in peer-type out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) - out.ValueSpecs = *(*[]ValueSpec)(unsafe.Pointer(&in.ValueSpecs)) + out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) + // WARNING: in.ResolvedPortSpecFields requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error { - out.Size = in.Size - out.VolumeType = in.VolumeType - out.AvailabilityZone = in.AvailabilityZone +func autoConvert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error { + // WARNING: in.Size requires manual conversion: does not exist in peer-type + // WARNING: in.VolumeType requires manual conversion: does not exist in peer-type + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function. -func Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in, out, s) -} - -func autoConvert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { - out.Size = in.Size - out.VolumeType = in.VolumeType - out.AvailabilityZone = in.AvailabilityZone +func autoConvert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error { + // WARNING: in.SizeGiB requires manual conversion: does not exist in peer-type + // WARNING: in.BlockDeviceVolume requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume is an autogenerated conversion function. -func Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in, out, s) -} - -func autoConvert_v1alpha6_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Router, s conversion.Scope) error { +func autoConvert_v1alpha6_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) @@ -1404,12 +1522,12 @@ func autoConvert_v1alpha6_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Ro return nil } -// Convert_v1alpha6_Router_To_v1alpha7_Router is an autogenerated conversion function. -func Convert_v1alpha6_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Router, s conversion.Scope) error { - return autoConvert_v1alpha6_Router_To_v1alpha7_Router(in, out, s) +// Convert_v1alpha6_Router_To_v1beta1_Router is an autogenerated conversion function. +func Convert_v1alpha6_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error { + return autoConvert_v1alpha6_Router_To_v1beta1_Router(in, out, s) } -func autoConvert_v1alpha7_Router_To_v1alpha6_Router(in *v1alpha7.Router, out *Router, s conversion.Scope) error { +func autoConvert_v1beta1_Router_To_v1alpha6_Router(in *v1beta1.Router, out *Router, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) @@ -1417,37 +1535,13 @@ func autoConvert_v1alpha7_Router_To_v1alpha6_Router(in *v1alpha7.Router, out *Ro return nil } -// Convert_v1alpha7_Router_To_v1alpha6_Router is an autogenerated conversion function. -func Convert_v1alpha7_Router_To_v1alpha6_Router(in *v1alpha7.Router, out *Router, s conversion.Scope) error { - return autoConvert_v1alpha7_Router_To_v1alpha6_Router(in, out, s) -} - -func autoConvert_v1alpha6_SecurityGroup_To_v1alpha7_SecurityGroup(in *SecurityGroup, out *v1alpha7.SecurityGroup, s conversion.Scope) error { - out.Name = in.Name - out.ID = in.ID - out.Rules = *(*[]v1alpha7.SecurityGroupRule)(unsafe.Pointer(&in.Rules)) - return nil -} - -// Convert_v1alpha6_SecurityGroup_To_v1alpha7_SecurityGroup is an autogenerated conversion function. -func Convert_v1alpha6_SecurityGroup_To_v1alpha7_SecurityGroup(in *SecurityGroup, out *v1alpha7.SecurityGroup, s conversion.Scope) error { - return autoConvert_v1alpha6_SecurityGroup_To_v1alpha7_SecurityGroup(in, out, s) +// Convert_v1beta1_Router_To_v1alpha6_Router is an autogenerated conversion function. +func Convert_v1beta1_Router_To_v1alpha6_Router(in *v1beta1.Router, out *Router, s conversion.Scope) error { + return autoConvert_v1beta1_Router_To_v1alpha6_Router(in, out, s) } -func autoConvert_v1alpha7_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha7.SecurityGroup, out *SecurityGroup, s conversion.Scope) error { - out.Name = in.Name - out.ID = in.ID - out.Rules = *(*[]SecurityGroupRule)(unsafe.Pointer(&in.Rules)) - return nil -} - -// Convert_v1alpha7_SecurityGroup_To_v1alpha6_SecurityGroup is an autogenerated conversion function. -func Convert_v1alpha7_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha7.SecurityGroup, out *SecurityGroup, s conversion.Scope) error { - return autoConvert_v1alpha7_SecurityGroup_To_v1alpha6_SecurityGroup(in, out, s) -} - -func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha7.SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID +func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type out.Name = in.Name out.Description = in.Description // WARNING: in.TenantID requires manual conversion: does not exist in peer-type @@ -1456,69 +1550,35 @@ func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in // WARNING: in.Marker requires manual conversion: does not exist in peer-type // WARNING: in.SortKey requires manual conversion: does not exist in peer-type // WARNING: in.SortDir requires manual conversion: does not exist in peer-type - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type return nil } -func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha7.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID +func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter is an autogenerated conversion function. -func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha7.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - return autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s) -} - -func autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha7.SecurityGroupRule, s conversion.Scope) error { - out.Description = in.Description - out.ID = in.ID - out.Direction = in.Direction - out.EtherType = in.EtherType - out.SecurityGroupID = in.SecurityGroupID - out.PortRangeMin = in.PortRangeMin - out.PortRangeMax = in.PortRangeMax - out.Protocol = in.Protocol - out.RemoteGroupID = in.RemoteGroupID - out.RemoteIPPrefix = in.RemoteIPPrefix +func autoConvert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *v1beta1.SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.Name requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.SecurityGroupFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter) return nil } -// Convert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule is an autogenerated conversion function. -func Convert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha7.SecurityGroupRule, s conversion.Scope) error { - return autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in, out, s) -} - -func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha7.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error { - out.Description = in.Description - out.ID = in.ID - out.Direction = in.Direction - out.EtherType = in.EtherType - out.SecurityGroupID = in.SecurityGroupID - out.PortRangeMin = in.PortRangeMin - out.PortRangeMax = in.PortRangeMax - out.Protocol = in.Protocol - out.RemoteGroupID = in.RemoteGroupID - out.RemoteIPPrefix = in.RemoteIPPrefix +func autoConvert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(in *v1beta1.SecurityGroupParam, out *SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.SecurityGroupFilter) return nil } -// Convert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule is an autogenerated conversion function. -func Convert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha7.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error { - return autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in, out, s) -} - -func autoConvert_v1alpha6_Subnet_To_v1alpha7_Subnet(in *Subnet, out *v1alpha7.Subnet, s conversion.Scope) error { +func autoConvert_v1alpha6_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.CIDR = in.CIDR @@ -1526,12 +1586,12 @@ func autoConvert_v1alpha6_Subnet_To_v1alpha7_Subnet(in *Subnet, out *v1alpha7.Su return nil } -// Convert_v1alpha6_Subnet_To_v1alpha7_Subnet is an autogenerated conversion function. -func Convert_v1alpha6_Subnet_To_v1alpha7_Subnet(in *Subnet, out *v1alpha7.Subnet, s conversion.Scope) error { - return autoConvert_v1alpha6_Subnet_To_v1alpha7_Subnet(in, out, s) +// Convert_v1alpha6_Subnet_To_v1beta1_Subnet is an autogenerated conversion function. +func Convert_v1alpha6_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { + return autoConvert_v1alpha6_Subnet_To_v1beta1_Subnet(in, out, s) } -func autoConvert_v1alpha7_Subnet_To_v1alpha6_Subnet(in *v1alpha7.Subnet, out *Subnet, s conversion.Scope) error { +func autoConvert_v1beta1_Subnet_To_v1alpha6_Subnet(in *v1beta1.Subnet, out *Subnet, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID out.CIDR = in.CIDR @@ -1539,12 +1599,12 @@ func autoConvert_v1alpha7_Subnet_To_v1alpha6_Subnet(in *v1alpha7.Subnet, out *Su return nil } -// Convert_v1alpha7_Subnet_To_v1alpha6_Subnet is an autogenerated conversion function. -func Convert_v1alpha7_Subnet_To_v1alpha6_Subnet(in *v1alpha7.Subnet, out *Subnet, s conversion.Scope) error { - return autoConvert_v1alpha7_Subnet_To_v1alpha6_Subnet(in, out, s) +// Convert_v1beta1_Subnet_To_v1alpha6_Subnet is an autogenerated conversion function. +func Convert_v1beta1_Subnet_To_v1alpha6_Subnet(in *v1beta1.Subnet, out *Subnet, s conversion.Scope) error { + return autoConvert_v1beta1_Subnet_To_v1alpha6_Subnet(in, out, s) } -func autoConvert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter, out *v1alpha7.SubnetFilter, s conversion.Scope) error { +func autoConvert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1553,20 +1613,15 @@ func autoConvert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter out.CIDR = in.CIDR out.IPv6AddressMode = in.IPv6AddressMode out.IPv6RAMode = in.IPv6RAMode - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter is an autogenerated conversion function. -func Convert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter, out *v1alpha7.SubnetFilter, s conversion.Scope) error { - return autoConvert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s) -} - -func autoConvert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha7.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { +func autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1575,39 +1630,42 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha7.Sub out.CIDR = in.CIDR out.IPv6AddressMode = in.IPv6AddressMode out.IPv6RAMode = in.IPv6RAMode - out.ID = in.ID - out.Tags = in.Tags - out.TagsAny = in.TagsAny - out.NotTags = in.NotTags - out.NotTagsAny = in.NotTagsAny + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha6_SubnetParam_To_v1beta1_SubnetParam(in *SubnetParam, out *v1beta1.SubnetParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.SubnetFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SubnetFilter) return nil } -// Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter is an autogenerated conversion function. -func Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha7.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { - return autoConvert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(in, out, s) +func autoConvert_v1beta1_SubnetParam_To_v1alpha6_SubnetParam(in *v1beta1.SubnetParam, out *SubnetParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SubnetFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.SubnetFilter) + return nil } -func autoConvert_v1alpha6_ValueSpec_To_v1alpha7_ValueSpec(in *ValueSpec, out *v1alpha7.ValueSpec, s conversion.Scope) error { +func autoConvert_v1alpha6_ValueSpec_To_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error { out.Name = in.Name out.Key = in.Key out.Value = in.Value return nil } -// Convert_v1alpha6_ValueSpec_To_v1alpha7_ValueSpec is an autogenerated conversion function. -func Convert_v1alpha6_ValueSpec_To_v1alpha7_ValueSpec(in *ValueSpec, out *v1alpha7.ValueSpec, s conversion.Scope) error { - return autoConvert_v1alpha6_ValueSpec_To_v1alpha7_ValueSpec(in, out, s) +// Convert_v1alpha6_ValueSpec_To_v1beta1_ValueSpec is an autogenerated conversion function. +func Convert_v1alpha6_ValueSpec_To_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error { + return autoConvert_v1alpha6_ValueSpec_To_v1beta1_ValueSpec(in, out, s) } -func autoConvert_v1alpha7_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha7.ValueSpec, out *ValueSpec, s conversion.Scope) error { +func autoConvert_v1beta1_ValueSpec_To_v1alpha6_ValueSpec(in *v1beta1.ValueSpec, out *ValueSpec, s conversion.Scope) error { out.Name = in.Name out.Key = in.Key out.Value = in.Value return nil } -// Convert_v1alpha7_ValueSpec_To_v1alpha6_ValueSpec is an autogenerated conversion function. -func Convert_v1alpha7_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha7.ValueSpec, out *ValueSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_ValueSpec_To_v1alpha6_ValueSpec(in, out, s) +// Convert_v1beta1_ValueSpec_To_v1alpha6_ValueSpec is an autogenerated conversion function. +func Convert_v1beta1_ValueSpec_To_v1alpha6_ValueSpec(in *v1beta1.ValueSpec, out *ValueSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ValueSpec_To_v1alpha6_ValueSpec(in, out, s) } diff --git a/api/v1alpha6/zz_generated.deepcopy.go b/api/v1alpha6/zz_generated.deepcopy.go index 42814ca63b..fb7166422e 100644 --- a/api/v1alpha6/zz_generated.deepcopy.go +++ b/api/v1alpha6/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go deleted file mode 100644 index 4bbb9d0e7a..0000000000 --- a/api/v1alpha7/conversion.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -// Hub marks OpenStackCluster as a conversion hub. -func (*OpenStackCluster) Hub() {} - -// Hub marks OpenStackClusterList as a conversion hub. -func (*OpenStackClusterList) Hub() {} - -// Hub marks OpenStackClusterTemplate as a conversion hub. -func (*OpenStackClusterTemplate) Hub() {} - -// Hub marks OpenStackClusterTemplateList as a conversion hub. -func (*OpenStackClusterTemplateList) Hub() {} - -// Hub marks OpenStackMachine as a conversion hub. -func (*OpenStackMachine) Hub() {} - -// Hub marks OpenStackMachineList as a conversion hub. -func (*OpenStackMachineList) Hub() {} - -// Hub marks OpenStackMachineTemplate as a conversion hub. -func (*OpenStackMachineTemplate) Hub() {} - -// Hub marks OpenStackMachineTemplateList as a conversion hub. -func (*OpenStackMachineTemplateList) Hub() {} diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go new file mode 100644 index 0000000000..9cdf570afc --- /dev/null +++ b/api/v1alpha7/conversion_test.go @@ -0,0 +1,410 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha7 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + fuzz "github.com/google/gofuzz" + "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/utils/ptr" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/internal/futures" + testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers" +) + +// Setting this to false to avoid running tests in parallel. Only for use in development. +const parallel = true + +func runParallel(f func(t *testing.T)) func(t *testing.T) { + if parallel { + return func(t *testing.T) { + t.Helper() + t.Parallel() + f(t) + } + } + return f +} + +func TestFuzzyConversion(t *testing.T) { + // The test already ignores the data annotation added on up-conversion. + // Also ignore the data annotation added on down-conversion. + ignoreDataAnnotation := func(hub conversion.Hub) { + obj := hub.(metav1.Object) + delete(obj.GetAnnotations(), utilconversion.DataAnnotation) + } + + fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} { + v1alpha7FuzzerFuncs := []interface{}{ + func(spec *OpenStackMachineSpec, c fuzz.Continue) { + c.FuzzNoCustom(spec) + + // RandString() generates strings up to 20 + // characters long. To exercise truncation of + // long server metadata keys and values we need + // the possibility of strings > 255 chars. + genLongString := func() string { + var ret string + for len(ret) < 255 { + ret += c.RandString() + } + return ret + } + + // Existing server metadata keys will be short. Add a random number of long ones. + for c.RandBool() { + if spec.ServerMetadata == nil { + spec.ServerMetadata = map[string]string{} + } + spec.ServerMetadata[genLongString()] = c.RandString() + } + + // Randomly make some server metadata values long. + for k := range spec.ServerMetadata { + if c.RandBool() { + spec.ServerMetadata[k] = genLongString() + } + } + }, + } + + return futures.SlicesConcat(v1alpha7FuzzerFuncs, testhelpers.InfraV1FuzzerFuncs()) + } + + t.Run("for OpenStackCluster", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackCluster{}, + Spoke: &OpenStackCluster{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackCluster with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ + FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackCluster{}, + Spoke: &OpenStackCluster{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackClusterTemplate", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackClusterTemplate{}, + Spoke: &OpenStackClusterTemplate{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackClusterTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ + FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackClusterTemplate{}, + Spoke: &OpenStackClusterTemplate{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackMachine", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackMachine{}, + Spoke: &OpenStackMachine{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackMachine with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ + FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackMachine{}, + Spoke: &OpenStackMachine{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackMachineTemplate", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackMachineTemplate{}, + Spoke: &OpenStackMachineTemplate{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) + + t.Run("for OpenStackMachineTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{ + FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{ + Hub: &infrav1.OpenStackMachineTemplate{}, + Spoke: &OpenStackMachineTemplate{}, + HubAfterMutation: ignoreDataAnnotation, + FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }, + MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs}, + }))) +} + +func TestMachineConversionControllerSpecFields(t *testing.T) { + // This tests that we still do field restoration when the controller modifies ProviderID and InstanceID in the spec + + // Define an initial state which cannot be converted losslessly. We add + // an IdentityRef with a Kind, which has been removed in v1beta1. + testMachine := func() *OpenStackMachine { + return &OpenStackMachine{ + Spec: OpenStackMachineSpec{ + IdentityRef: &OpenStackIdentityReference{ + Kind: "InvalidKind", + Name: "test-name", + }, + }, + } + } + + tests := []struct { + name string + modifyUp func(*infrav1.OpenStackMachine) + testAfter func(gomega.Gomega, *OpenStackMachine) + expectIdentityRefDiff bool + }{ + { + name: "No change", + }, + { + name: "Non-ignored change", + modifyUp: func(up *infrav1.OpenStackMachine) { + up.Spec.Flavor = "new-flavor" + }, + testAfter: func(g gomega.Gomega, after *OpenStackMachine) { + g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor")) + }, + expectIdentityRefDiff: true, + }, + { + name: "Set ProviderID", + modifyUp: func(up *infrav1.OpenStackMachine) { + up.Spec.ProviderID = ptr.To("new-provider-id") + }, + testAfter: func(g gomega.Gomega, after *OpenStackMachine) { + g.Expect(after.Spec.ProviderID).To(gomega.Equal(ptr.To("new-provider-id"))) + }, + expectIdentityRefDiff: false, + }, + { + name: "Set InstanceID", + modifyUp: func(up *infrav1.OpenStackMachine) { + up.Status.InstanceID = ptr.To("new-instance-id") + }, + testAfter: func(g gomega.Gomega, after *OpenStackMachine) { + g.Expect(after.Spec.InstanceID).To(gomega.Equal(ptr.To("new-instance-id"))) + }, + expectIdentityRefDiff: false, + }, + { + name: "Set ProviderID and non-ignored change", + modifyUp: func(up *infrav1.OpenStackMachine) { + up.Spec.ProviderID = ptr.To("new-provider-id") + up.Spec.Flavor = "new-flavor" + }, + testAfter: func(g gomega.Gomega, after *OpenStackMachine) { + g.Expect(after.Spec.ProviderID).To(gomega.Equal(ptr.To("new-provider-id"))) + g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor")) + }, + expectIdentityRefDiff: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + scheme := runtime.NewScheme() + g.Expect(AddToScheme(scheme)).To(gomega.Succeed()) + g.Expect(infrav1.AddToScheme(scheme)).To(gomega.Succeed()) + + before := testMachine() + + up := infrav1.OpenStackMachine{} + g.Expect(before.ConvertTo(&up)).To(gomega.Succeed()) + + if tt.modifyUp != nil { + tt.modifyUp(&up) + } + + after := OpenStackMachine{} + g.Expect(after.ConvertFrom(&up)).To(gomega.Succeed()) + + if tt.testAfter != nil { + tt.testAfter(g, &after) + } + + g.Expect(after.Spec.IdentityRef).ToNot(gomega.BeNil()) + if tt.expectIdentityRefDiff { + g.Expect(after.Spec.IdentityRef.Kind).ToNot(gomega.Equal("InvalidKind")) + } else { + g.Expect(after.Spec.IdentityRef.Kind).To(gomega.Equal("InvalidKind")) + } + }) + } +} + +func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t *testing.T) { + tests := []struct { + name string + in *OpenStackClusterSpec + expectedOut *infrav1.OpenStackClusterSpec + }{ + { + name: "empty", + in: &OpenStackClusterSpec{}, + expectedOut: &infrav1.OpenStackClusterSpec{}, + }, + { + name: "with managed security groups and not allow all in cluster traffic", + in: &OpenStackClusterSpec{ + ManagedSecurityGroups: true, + AllowAllInClusterTraffic: false, + }, + expectedOut: &infrav1.OpenStackClusterSpec{ + ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{ + AllNodesSecurityGroupRules: infrav1.LegacyCalicoSecurityGroupRules(), + }, + }, + }, + { + name: "with managed security groups and allow all in cluster traffic", + in: &OpenStackClusterSpec{ + ManagedSecurityGroups: true, + AllowAllInClusterTraffic: true, + }, + expectedOut: &infrav1.OpenStackClusterSpec{ + ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{ + AllowAllInClusterTraffic: true, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + out := &infrav1.OpenStackClusterSpec{} + err := Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in.DeepCopy(), out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(out).To(gomega.Equal(tt.expectedOut), cmp.Diff(out, tt.expectedOut)) + }) + + t.Run("template_"+tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + in := &OpenStackClusterTemplateSpec{ + Template: OpenStackClusterTemplateResource{ + Spec: *(tt.in.DeepCopy()), + }, + } + out := &infrav1.OpenStackClusterTemplateSpec{} + err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in, out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(&out.Template.Spec).To(gomega.Equal(tt.expectedOut), cmp.Diff(&out.Template.Spec, tt.expectedOut)) + }) + } +} + +func TestConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(t *testing.T) { + tests := []struct { + name string + in *OpenStackMachineSpec + expectedOut *infrav1.OpenStackMachineSpec + }{ + { + name: "empty", + in: &OpenStackMachineSpec{}, + expectedOut: &infrav1.OpenStackMachineSpec{}, + }, + { + name: "empty port", + in: &OpenStackMachineSpec{ + Ports: []PortOpts{{}}, + }, + expectedOut: &infrav1.OpenStackMachineSpec{ + Ports: []infrav1.PortOpts{{}}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + out := &infrav1.OpenStackMachineSpec{} + err := Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(tt.in.DeepCopy(), out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(out).To(gomega.Equal(tt.expectedOut), cmp.Diff(out, tt.expectedOut)) + }) + + t.Run("template_"+tt.name, func(t *testing.T) { + g := gomega.NewWithT(t) + in := &OpenStackMachineTemplateSpec{ + Template: OpenStackMachineTemplateResource{ + Spec: *(tt.in.DeepCopy()), + }, + } + out := &infrav1.OpenStackMachineTemplateSpec{} + err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in, out, nil) + g.Expect(err).NotTo(gomega.HaveOccurred()) + g.Expect(&out.Template.Spec).To(gomega.Equal(tt.expectedOut), cmp.Diff(&out.Template.Spec, tt.expectedOut)) + }) + } +} + +func Test_FuzzRestorers(t *testing.T) { + /* Cluster */ + testhelpers.FuzzRestorer(t, "restorev1alpha7ClusterSpec", restorev1alpha7ClusterSpec) + testhelpers.FuzzRestorer(t, "restorev1beta1ClusterSpec", restorev1beta1ClusterSpec) + testhelpers.FuzzRestorer(t, "restorev1alpha7ClusterStatus", restorev1alpha7ClusterStatus) + testhelpers.FuzzRestorer(t, "restorev1beta1ClusterStatus", restorev1beta1ClusterStatus) + testhelpers.FuzzRestorer(t, "restorev1alpha7Bastion", restorev1alpha7Bastion) + testhelpers.FuzzRestorer(t, "restorev1beta1Bastion", restorev1beta1Bastion) + testhelpers.FuzzRestorer(t, "restorev1beta1BastionStatus", restorev1beta1BastionStatus) + + /* ClusterTemplate */ + testhelpers.FuzzRestorer(t, "restorev1alpha7ClusterTemplateSpec", restorev1alpha7ClusterTemplateSpec) + testhelpers.FuzzRestorer(t, "restorev1alpha7ClusterTemplateSpec", restorev1alpha7ClusterTemplateSpec) + + /* Machine */ + testhelpers.FuzzRestorer(t, "restorev1alpha7MachineSpec", restorev1alpha7MachineSpec) + testhelpers.FuzzRestorer(t, "restorev1beta1MachineSpec", restorev1beta1MachineSpec) + + /* MachineTemplate */ + testhelpers.FuzzRestorer(t, "restorev1alpha7MachineTemplateSpec", restorev1alpha7MachineTemplateSpec) + + /* Types */ + testhelpers.FuzzRestorer(t, "restorev1alpha7SecurityGroupFilter", restorev1alpha7SecurityGroupFilter) + testhelpers.FuzzRestorer(t, "restorev1alpha7SecurityGroup", restorev1alpha7SecurityGroup) + testhelpers.FuzzRestorer(t, "restorev1beta1SecurityGroupParam", restorev1beta1SecurityGroupParam) + testhelpers.FuzzRestorer(t, "restorev1alpha7NetworkFilter", restorev1alpha7NetworkFilter) + testhelpers.FuzzRestorer(t, "restorev1beta1NetworkParam", restorev1beta1NetworkParam) + testhelpers.FuzzRestorer(t, "restorev1alpha7SubnetFilter", restorev1alpha7SubnetFilter) + testhelpers.FuzzRestorer(t, "restorev1beta1SubnetParam", restorev1beta1SubnetParam) + testhelpers.FuzzRestorer(t, "restorev1alpha7RouterFilter", restorev1alpha7RouterFilter) + testhelpers.FuzzRestorer(t, "restorev1beta1RouterParam", restorev1beta1RouterParam) + testhelpers.FuzzRestorer(t, "restorev1alpha7Port", restorev1alpha7Port) + testhelpers.FuzzRestorer(t, "restorev1beta1Port", restorev1beta1Port) + testhelpers.FuzzRestorer(t, "restorev1beta1APIServerLoadBalancer", restorev1beta1APIServerLoadBalancer) + testhelpers.FuzzRestorer(t, "restorev1beta1BlockDeviceVolume", restorev1beta1BlockDeviceVolume) +} diff --git a/api/v1alpha7/doc.go b/api/v1alpha7/doc.go index 817c2b4119..0c61ce4c18 100644 --- a/api/v1alpha7/doc.go +++ b/api/v1alpha7/doc.go @@ -14,4 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Package v1alpha7 contains API Schema definitions for the infrastructure v1alpha7 API group. +// +kubebuilder:object:generate=true +// +groupName=infrastructure.cluster.x-k8s.io +// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1 package v1alpha7 diff --git a/api/v1alpha7/filter_convert.go b/api/v1alpha7/filter_convert.go deleted file mode 100644 index 236c91fcd7..0000000000 --- a/api/v1alpha7/filter_convert.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" - securitygroups "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" -) - -func (securityGroupFilter SecurityGroupFilter) ToListOpt() securitygroups.ListOpts { - return securitygroups.ListOpts{ - ID: securityGroupFilter.ID, - Name: securityGroupFilter.Name, - Description: securityGroupFilter.Description, - ProjectID: securityGroupFilter.ProjectID, - Tags: securityGroupFilter.Tags, - TagsAny: securityGroupFilter.TagsAny, - NotTags: securityGroupFilter.NotTags, - NotTagsAny: securityGroupFilter.NotTagsAny, - } -} - -func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts { - return subnets.ListOpts{ - Name: subnetFilter.Name, - Description: subnetFilter.Description, - ProjectID: subnetFilter.ProjectID, - IPVersion: subnetFilter.IPVersion, - GatewayIP: subnetFilter.GatewayIP, - CIDR: subnetFilter.CIDR, - IPv6AddressMode: subnetFilter.IPv6AddressMode, - IPv6RAMode: subnetFilter.IPv6RAMode, - ID: subnetFilter.ID, - Tags: subnetFilter.Tags, - TagsAny: subnetFilter.TagsAny, - NotTags: subnetFilter.NotTags, - NotTagsAny: subnetFilter.NotTagsAny, - } -} - -func (networkFilter NetworkFilter) ToListOpt() networks.ListOpts { - return networks.ListOpts{ - Name: networkFilter.Name, - Description: networkFilter.Description, - ProjectID: networkFilter.ProjectID, - ID: networkFilter.ID, - Tags: networkFilter.Tags, - TagsAny: networkFilter.TagsAny, - NotTags: networkFilter.NotTags, - NotTagsAny: networkFilter.NotTagsAny, - } -} - -func (routerFilter RouterFilter) ToListOpt() routers.ListOpts { - return routers.ListOpts{ - ID: routerFilter.ID, - Name: routerFilter.Name, - Description: routerFilter.Description, - ProjectID: routerFilter.ProjectID, - Tags: routerFilter.Tags, - TagsAny: routerFilter.TagsAny, - NotTags: routerFilter.NotTags, - NotTagsAny: routerFilter.NotTagsAny, - } -} diff --git a/api/v1alpha7/groupversion_info.go b/api/v1alpha7/groupversion_info.go index 019caf4f0f..e3aadf9ff5 100644 --- a/api/v1alpha7/groupversion_info.go +++ b/api/v1alpha7/groupversion_info.go @@ -14,9 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// package v1alpha7 contains API Schema definitions for the infrastructure v1alpha7 API group -// +kubebuilder:object:generate=true -// +groupName=infrastructure.cluster.x-k8s.io package v1alpha7 import ( @@ -33,4 +30,6 @@ var ( // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme + + localSchemeBuilder = SchemeBuilder.SchemeBuilder ) diff --git a/api/v1alpha7/identity_types.go b/api/v1alpha7/identity_types.go index 15cd58562b..1ea5f2fb9b 100644 --- a/api/v1alpha7/identity_types.go +++ b/api/v1alpha7/identity_types.go @@ -16,8 +16,6 @@ limitations under the License. package v1alpha7 -const defaultIdentityRefKind = "Secret" - // OpenStackIdentityReference is a reference to an infrastructure // provider identity to be used to provision cluster resources. type OpenStackIdentityReference struct { diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go new file mode 100644 index 0000000000..96e03b5c87 --- /dev/null +++ b/api/v1alpha7/openstackcluster_conversion.go @@ -0,0 +1,490 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha7 + +import ( + "reflect" + + apiconversion "k8s.io/apimachinery/pkg/conversion" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" +) + +var _ ctrlconversion.Convertible = &OpenStackCluster{} + +func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackCluster) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster, Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster, + v1alpha7OpenStackClusterRestorer, v1beta1OpenStackClusterRestorer, + ) +} + +func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackCluster) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster, + v1beta1OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackClusterList{} + +func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterList) + + return Convert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList(r, dst, nil) +} + +func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterList) + + return Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(src, r, nil) +} + +/* Restorers */ + +var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{ + "bastion": conversion.HashedFieldRestorer( + func(c *OpenStackCluster) **Bastion { + return &c.Spec.Bastion + }, + restorev1alpha7Bastion, + ), + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackCluster) *OpenStackClusterSpec { + return &c.Spec + }, + restorev1alpha7ClusterSpec, + // Filter out Bastion, which is restored separately, and + // ControlPlaneEndpoint, which is written by the cluster controller + conversion.HashedFilterField[*OpenStackCluster]( + func(s *OpenStackClusterSpec) *OpenStackClusterSpec { + if s.Bastion != nil || s.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) { + f := *s + f.Bastion = nil + f.ControlPlaneEndpoint = clusterv1.APIEndpoint{} + return &f + } + return s + }, + ), + ), + "status": conversion.HashedFieldRestorer( + func(c *OpenStackCluster) *OpenStackClusterStatus { + return &c.Status + }, + restorev1alpha7ClusterStatus, + ), +} + +var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{ + "bastion": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackCluster) **infrav1.Bastion { + return &c.Spec.Bastion + }, + restorev1beta1Bastion, + ), + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterSpec { + return &c.Spec + }, + restorev1beta1ClusterSpec, + // Filter out Bastion, which is restored separately + conversion.HashedFilterField[*infrav1.OpenStackCluster, infrav1.OpenStackClusterSpec]( + func(s *infrav1.OpenStackClusterSpec) *infrav1.OpenStackClusterSpec { + if s.Bastion != nil { + f := *s + f.Bastion = nil + return &f + } + return s + }, + ), + ), + "status": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus { + return &c.Status + }, + restorev1beta1ClusterStatus, + ), +} + +/* OpenStackClusterSpec */ + +func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) { + prevBastion := previous.Bastion + dstBastion := dst.Bastion + if prevBastion != nil && dstBastion != nil { + restorev1alpha7MachineSpec(&prevBastion.Instance, &dstBastion.Instance) + } + + // We only restore DNSNameservers when these were lossly converted when NodeCIDR is empty. + if len(previous.DNSNameservers) > 0 && dst.NodeCIDR == "" { + dst.DNSNameservers = previous.DNSNameservers + } + + // To avoid lossy conversion, we need to restore AllowAllInClusterTraffic + // even if ManagedSecurityGroups is set to false + if previous.AllowAllInClusterTraffic && !previous.ManagedSecurityGroups { + dst.AllowAllInClusterTraffic = true + } + + // Conversion to v1beta1 removes the Kind field + dst.IdentityRef = previous.IdentityRef + + if len(dst.ExternalRouterIPs) == len(previous.ExternalRouterIPs) { + for i := range dst.ExternalRouterIPs { + restorev1alpha7SubnetFilter(&previous.ExternalRouterIPs[i].Subnet, &dst.ExternalRouterIPs[i].Subnet) + } + } + + restorev1alpha7SubnetFilter(&previous.Subnet, &dst.Subnet) + + if dst.Router != nil && previous.Router != nil { + restorev1alpha7RouterFilter(previous.Router, dst.Router) + } + + restorev1alpha7NetworkFilter(&previous.Network, &dst.Network) +} + +func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) { + if previous == nil || dst == nil { + return + } + + // Bastion is restored separately + + if dst.Network == nil { + dst.Network = previous.Network + } + + // ExternalNetwork by filter will be been lost in down-conversion + if previous.ExternalNetwork != nil { + if dst.ExternalNetwork == nil { + dst.ExternalNetwork = &infrav1.NetworkParam{} + } + dst.ExternalNetwork.Filter = previous.ExternalNetwork.Filter + } + + dst.DisableExternalNetwork = previous.DisableExternalNetwork + + restorev1beta1RouterParam(previous.Router, dst.Router) + restorev1beta1NetworkParam(previous.Network, dst.Network) + + if len(previous.Subnets) > 0 && len(dst.Subnets) > 0 { + restorev1beta1SubnetParam(&previous.Subnets[0], &dst.Subnets[0]) + } + if len(previous.Subnets) > 1 { + dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...) + } + + if len(previous.ExternalRouterIPs) == len(dst.ExternalRouterIPs) { + for i := range dst.ExternalRouterIPs { + restorev1beta1SubnetParam(&previous.ExternalRouterIPs[i].Subnet, &dst.ExternalRouterIPs[i].Subnet) + } + } + + dst.ManagedSubnets = previous.ManagedSubnets + + if previous.ManagedSecurityGroups != nil && dst.ManagedSecurityGroups != nil { + dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules + } + + if dst.APIServerLoadBalancer != nil && previous.APIServerLoadBalancer != nil { + if dst.APIServerLoadBalancer.Enabled == nil || !*dst.APIServerLoadBalancer.Enabled { + dst.APIServerLoadBalancer.Enabled = previous.APIServerLoadBalancer.Enabled + } + optional.RestoreString(&previous.APIServerLoadBalancer.Provider, &dst.APIServerLoadBalancer.Provider) + + if previous.APIServerLoadBalancer.Network != nil { + dst.APIServerLoadBalancer.Network = previous.APIServerLoadBalancer.Network + } + + if previous.APIServerLoadBalancer.Subnets != nil { + dst.APIServerLoadBalancer.Subnets = previous.APIServerLoadBalancer.Subnets + } + } + if dst.APIServerLoadBalancer.IsZero() { + dst.APIServerLoadBalancer = previous.APIServerLoadBalancer + } + + if dst.ControlPlaneEndpoint == nil || *dst.ControlPlaneEndpoint == (clusterv1.APIEndpoint{}) { + dst.ControlPlaneEndpoint = previous.ControlPlaneEndpoint + } + + optional.RestoreString(&previous.APIServerFloatingIP, &dst.APIServerFloatingIP) + optional.RestoreString(&previous.APIServerFixedIP, &dst.APIServerFixedIP) + optional.RestoreInt(&previous.APIServerPort, &dst.APIServerPort) + optional.RestoreBool(&previous.DisableAPIServerFloatingIP, &dst.DisableAPIServerFloatingIP) + optional.RestoreBool(&previous.ControlPlaneOmitAvailabilityZone, &dst.ControlPlaneOmitAvailabilityZone) + optional.RestoreBool(&previous.DisablePortSecurity, &dst.DisablePortSecurity) + + restorev1beta1APIServerLoadBalancer(previous.APIServerLoadBalancer, dst.APIServerLoadBalancer) +} + +func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Network != (NetworkFilter{}) { + out.Network = &infrav1.NetworkParam{} + if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkParam(&in.Network, out.Network, s); err != nil { + return err + } + } + + if in.ExternalNetworkID != "" { + out.ExternalNetwork = &infrav1.NetworkParam{ + ID: &in.ExternalNetworkID, + } + } + + emptySubnet := SubnetFilter{} + if in.Subnet != emptySubnet { + subnet := infrav1.SubnetParam{} + if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &subnet, s); err != nil { + return err + } + out.Subnets = []infrav1.SubnetParam{subnet} + } + + // DNSNameservers without NodeCIDR doesn't make sense, so we drop that. + if len(in.NodeCIDR) > 0 { + out.ManagedSubnets = []infrav1.SubnetSpec{ + { + CIDR: in.NodeCIDR, + DNSNameservers: in.DNSNameservers, + }, + } + } + + if in.ManagedSecurityGroups { + out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{} + if !in.AllowAllInClusterTraffic { + out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules() + } else { + out.ManagedSecurityGroups.AllowAllInClusterTraffic = true + } + } + + if in.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) { + out.ControlPlaneEndpoint = &in.ControlPlaneEndpoint + } + + out.IdentityRef.CloudName = in.CloudName + if in.IdentityRef != nil { + out.IdentityRef.Name = in.IdentityRef.Name + } + + apiServerLoadBalancer := &infrav1.APIServerLoadBalancer{} + if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, apiServerLoadBalancer, s); err != nil { + return err + } + if !apiServerLoadBalancer.IsZero() { + out.APIServerLoadBalancer = apiServerLoadBalancer + } + + return nil +} + +func Convert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s apiconversion.Scope) error { + return autoConvert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s) +} + +func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s apiconversion.Scope) error { + return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s) +} + +func Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *infrav1.APIServerLoadBalancer, s apiconversion.Scope) error { + return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s) +} + +func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Network != nil { + if err := Convert_v1beta1_NetworkParam_To_v1alpha7_NetworkFilter(in.Network, &out.Network, s); err != nil { + return err + } + } + + if in.ExternalNetwork != nil && in.ExternalNetwork.ID != nil { + out.ExternalNetworkID = *in.ExternalNetwork.ID + } + + if len(in.Subnets) >= 1 { + if err := Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil { + return err + } + } + + if len(in.ManagedSubnets) > 0 { + out.NodeCIDR = in.ManagedSubnets[0].CIDR + out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers + } + + if in.ManagedSecurityGroups != nil { + out.ManagedSecurityGroups = true + out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic + } + + if in.ControlPlaneEndpoint != nil { + out.ControlPlaneEndpoint = *in.ControlPlaneEndpoint + } + + out.CloudName = in.IdentityRef.CloudName + out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name} + + if in.APIServerLoadBalancer != nil { + if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil { + return err + } + } + + return nil +} + +/* OpenStackClusterStatus */ + +func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) { + restorev1alpha7SecurityGroup(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup) + restorev1alpha7SecurityGroup(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup) + restorev1alpha7SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup) +} + +func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) { + if previous == nil || dst == nil { + return + } + + restorev1beta1BastionStatus(previous.Bastion, dst.Bastion) + + if previous.APIServerLoadBalancer != nil { + dst.APIServerLoadBalancer = previous.APIServerLoadBalancer + } +} + +func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s) +} + +/* Bastion */ + +func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) { + if previous == nil || dst == nil || *previous == nil || *dst == nil { + return + } + prevMachineSpec := &(*previous).Instance + dstMachineSpec := &(*dst).Instance + restorev1alpha7MachineSpec(prevMachineSpec, dstMachineSpec) + dstMachineSpec.InstanceID = prevMachineSpec.InstanceID +} + +func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) { + if previous == nil || dst == nil || *previous == nil || *dst == nil { + return + } + + restorev1beta1MachineSpec((*previous).Spec, (*dst).Spec) + optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP) + optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone) + optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled) +} + +func Convert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error { + err := autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in, out, s) + if err != nil { + return err + } + + if !reflect.ValueOf(in.Instance).IsZero() { + out.Spec = &infrav1.OpenStackMachineSpec{} + + err = Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Spec, s) + if err != nil { + return err + } + + if in.Instance.ServerGroupID != "" { + out.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: &in.Instance.ServerGroupID} + } else { + out.Spec.ServerGroup = nil + } + + err = optional.Convert_string_To_optional_String(&in.Instance.FloatingIP, &out.FloatingIP, s) + if err != nil { + return err + } + } + + // nil the Spec if it's basically an empty object. + if out.Spec != nil && reflect.ValueOf(*out.Spec).IsZero() { + out.Spec = nil + } + return nil +} + +func Convert_v1beta1_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error { + err := autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in, out, s) + if err != nil { + return err + } + + if in.Spec != nil { + err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in.Spec, &out.Instance, s) + if err != nil { + return err + } + + if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != nil { + out.Instance.ServerGroupID = *in.Spec.ServerGroup.ID + } + } + + return optional.Convert_optional_String_To_string(&in.FloatingIP, &out.Instance.FloatingIP, s) +} + +/* Bastion status */ + +func restorev1beta1BastionStatus(previous *infrav1.BastionStatus, dst *infrav1.BastionStatus) { + if previous == nil || dst == nil { + return + } + + // Resolved and resources have no equivalents + dst.Resolved = previous.Resolved + dst.Resources = previous.Resources +} + +func Convert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *infrav1.BastionStatus, out *BastionStatus, s apiconversion.Scope) error { + // ReferencedResources have no equivalent in v1alpha7 + return autoConvert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in, out, s) +} diff --git a/api/v1alpha7/openstackcluster_types.go b/api/v1alpha7/openstackcluster_types.go index b4826685b0..ef0ea51702 100644 --- a/api/v1alpha7/openstackcluster_types.go +++ b/api/v1alpha7/openstackcluster_types.go @@ -229,9 +229,10 @@ type OpenStackClusterStatus struct { FailureMessage *string `json:"failureMessage,omitempty"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true // +kubebuilder:resource:path=openstackclusters,scope=Namespaced,categories=cluster-api,shortName=osc -// +kubebuilder:storageversion // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this OpenStackCluster belongs" // +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready",description="Cluster infrastructure is ready for OpenStack instances" diff --git a/api/v1alpha7/openstackcluster_webhook.go b/api/v1alpha7/openstackcluster_webhook.go deleted file mode 100644 index 706d10a8c6..0000000000 --- a/api/v1alpha7/openstackcluster_webhook.go +++ /dev/null @@ -1,153 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "fmt" - "reflect" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" - "sigs.k8s.io/controller-runtime/pkg/builder" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" -) - -// log is for logging in this package. -var _ = logf.Log.WithName("openstackcluster-resource") - -func (r *OpenStackCluster) SetupWebhookWithManager(mgr manager.Manager) error { - return builder.WebhookManagedBy(mgr). - For(r). - Complete() -} - -// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1alpha7,name=validation.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 -// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackcluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1alpha7,name=default.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 - -var ( - _ webhook.Defaulter = &OpenStackCluster{} - _ webhook.Validator = &OpenStackCluster{} -) - -// Default satisfies the defaulting webhook interface. -func (r *OpenStackCluster) Default() { - if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind == "" { - r.Spec.IdentityRef.Kind = defaultIdentityRefKind - } -} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackCluster) ValidateCreate() (admission.Warnings, error) { - var allErrs field.ErrorList - - if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind != defaultIdentityRefKind { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "identityRef", "kind"), "must be a Secret")) - } - - return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warnings, error) { - var allErrs field.ErrorList - old, ok := oldRaw.(*OpenStackCluster) - if !ok { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackCluster but got a %T", oldRaw)) - } - - if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind != defaultIdentityRefKind { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec", "identityRef", "kind"), - r.Spec.IdentityRef, "must be a Secret"), - ) - } - - // Allow changes to Spec.IdentityRef.Name. - if old.Spec.IdentityRef != nil && r.Spec.IdentityRef != nil { - old.Spec.IdentityRef.Name = "" - r.Spec.IdentityRef.Name = "" - } - - // Allow changes to Spec.IdentityRef if it was unset. - if old.Spec.IdentityRef == nil && r.Spec.IdentityRef != nil { - old.Spec.IdentityRef = &OpenStackIdentityReference{} - r.Spec.IdentityRef = &OpenStackIdentityReference{} - } - - if old.Spec.IdentityRef != nil && r.Spec.IdentityRef == nil { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec", "identityRef"), - r.Spec.IdentityRef, "field cannot be set to nil"), - ) - } - - // Allow change only for the first time. - if old.Spec.ControlPlaneEndpoint.Host == "" { - old.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{} - r.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{} - } - - // Allow change only for the first time. - if old.Spec.DisableAPIServerFloatingIP && old.Spec.APIServerFixedIP == "" { - r.Spec.APIServerFixedIP = "" - } - - // If API Server floating IP is disabled, allow the change of the API Server port only for the first time. - if old.Spec.DisableAPIServerFloatingIP && old.Spec.APIServerPort == 0 && r.Spec.APIServerPort > 0 { - r.Spec.APIServerPort = 0 - } - - // Allow changes to the bastion spec. - old.Spec.Bastion = &Bastion{} - r.Spec.Bastion = &Bastion{} - - // Allow changes on AllowedCIDRs - if r.Spec.APIServerLoadBalancer.Enabled { - old.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{} - r.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{} - } - - // Allow changes to the availability zones. - old.Spec.ControlPlaneAvailabilityZones = []string{} - r.Spec.ControlPlaneAvailabilityZones = []string{} - - // Allow change to the allowAllInClusterTraffic. - old.Spec.AllowAllInClusterTraffic = false - r.Spec.AllowAllInClusterTraffic = false - - // Allow change on the spec.APIServerFloatingIP only if it matches the current api server loadbalancer IP. - if old.Status.APIServerLoadBalancer != nil && r.Spec.APIServerFloatingIP == old.Status.APIServerLoadBalancer.IP { - r.Spec.APIServerFloatingIP = "" - old.Spec.APIServerFloatingIP = "" - } - - if !reflect.DeepEqual(old.Spec, r.Spec) { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified")) - } - - return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackCluster) ValidateDelete() (admission.Warnings, error) { - return nil, nil -} diff --git a/api/v1alpha7/openstackcluster_webhook_test.go b/api/v1alpha7/openstackcluster_webhook_test.go deleted file mode 100644 index 24e1407f2c..0000000000 --- a/api/v1alpha7/openstackcluster_webhook_test.go +++ /dev/null @@ -1,408 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "testing" - - . "github.com/onsi/gomega" -) - -func TestOpenStackCluster_ValidateUpdate(t *testing.T) { - g := NewWithT(t) - - tests := []struct { - name string - oldTemplate *OpenStackCluster - newTemplate *OpenStackCluster - wantErr bool - }{ - { - name: "OpenStackCluster.Spec.IdentityRef.Kind must always be Secret", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "Secret", - Name: "foobar", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "foobar", - Name: "foobar", - }, - }, - }, - wantErr: true, - }, - { - name: "Changing OpenStackCluster.Spec.IdentityRef.Name is allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "Secret", - Name: "foobar", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "Secret", - Name: "foobarbaz", - }, - }, - }, - wantErr: false, - }, - { - name: "OpenStackCluster.Spec.IdentityRef can be changed if it was unset", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "Secret", - Name: "foobar", - }, - }, - }, - wantErr: false, - }, - { - name: "OpenStackCluster.Spec.IdentityRef must not be removed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "Secret", - Name: "foobar", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - }, - }, - wantErr: true, - }, - { - name: "Changing OpenStackCluster.Spec.Bastion is allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - Bastion: &Bastion{ - Instance: OpenStackMachineSpec{ - CloudName: "foobar", - Image: "foobar", - Flavor: "minimal", - }, - Enabled: true, - }, - }, - Status: OpenStackClusterStatus{ - Bastion: &BastionStatus{ - Name: "foobar", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - Bastion: &Bastion{ - Instance: OpenStackMachineSpec{ - CloudName: "foobarbaz", - Image: "foobarbaz", - Flavor: "medium", - }, - Enabled: true, - }, - }, - }, - wantErr: false, - }, - { - name: "Changing CIDRs on the OpenStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs is allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - APIServerLoadBalancer: APIServerLoadBalancer{ - Enabled: true, - AllowedCIDRs: []string{ - "0.0.0.0/0", - "192.168.10.0/24", - }, - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - APIServerLoadBalancer: APIServerLoadBalancer{ - Enabled: true, - AllowedCIDRs: []string{ - "0.0.0.0/0", - "192.168.10.0/24", - "10.6.0.0/16", - }, - }, - }, - }, - wantErr: false, - }, - { - name: "Adding OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - ControlPlaneAvailabilityZones: []string{ - "alice", - "bob", - }, - }, - }, - wantErr: false, - }, - { - name: "Modifying OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - ControlPlaneAvailabilityZones: []string{ - "alice", - "bob", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - ControlPlaneAvailabilityZones: []string{ - "alice", - "bob", - "eve", - }, - }, - }, - wantErr: false, - }, - { - name: "Removing OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - ControlPlaneAvailabilityZones: []string{ - "alice", - "bob", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - }, - }, - wantErr: false, - }, - { - name: "Changing OpenStackCluster.Spec.APIServerFixedIP is allowed when API Server Floating IP is disabled", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: true, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: true, - APIServerFixedIP: "20.1.56.1", - }, - }, - wantErr: false, - }, - { - name: "Changing OpenStackCluster.Spec.APIServerFixedIP is not allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: false, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: false, - APIServerFixedIP: "20.1.56.1", - }, - }, - wantErr: true, - }, - - { - name: "Changing OpenStackCluster.Spec.APIServerPort is allowed when API Server Floating IP is disabled", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: true, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: true, - APIServerPort: 8443, - }, - }, - wantErr: false, - }, - { - name: "Changing OpenStackCluster.Spec.APIServerPort is not allowed", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: false, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - DisableAPIServerFloatingIP: false, - APIServerPort: 8443, - }, - }, - wantErr: true, - }, - { - name: "Changing OpenStackCluster.Spec.APIServerFloatingIP is allowed when it matches the current api server loadbalancer IP", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - APIServerFloatingIP: "", - }, - Status: OpenStackClusterStatus{ - APIServerLoadBalancer: &LoadBalancer{ - IP: "1.2.3.4", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - APIServerFloatingIP: "1.2.3.4", - }, - Status: OpenStackClusterStatus{ - APIServerLoadBalancer: &LoadBalancer{ - IP: "1.2.3.4", - }, - }, - }, - wantErr: false, - }, - { - name: "Changing OpenStackCluster.Spec.APIServerFloatingIP is not allowed when it doesn't matches the current api server loadbalancer IP", - oldTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - APIServerFloatingIP: "", - }, - Status: OpenStackClusterStatus{ - APIServerLoadBalancer: &LoadBalancer{ - IP: "1.2.3.4", - }, - }, - }, - newTemplate: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - APIServerFloatingIP: "5.6.7.8", - }, - Status: OpenStackClusterStatus{ - APIServerLoadBalancer: &LoadBalancer{ - IP: "1.2.3.4", - }, - }, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - warn, err := tt.newTemplate.ValidateUpdate(tt.oldTemplate) - if tt.wantErr { - g.Expect(err).To(HaveOccurred()) - } else { - g.Expect(err).NotTo(HaveOccurred()) - } - // Nothing emits warnings yet - g.Expect(warn).To(BeEmpty()) - }) - } -} - -func TestOpenStackCluster_ValidateCreate(t *testing.T) { - g := NewWithT(t) - - tests := []struct { - name string - template *OpenStackCluster - wantErr bool - }{ - { - name: "OpenStackCluster.Spec.IdentityRef with correct spec on create", - template: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "Secret", - Name: "foobar", - }, - }, - }, - wantErr: false, - }, - { - name: "OpenStackCluster.Spec.IdentityRef with faulty spec on create", - template: &OpenStackCluster{ - Spec: OpenStackClusterSpec{ - CloudName: "foobar", - IdentityRef: &OpenStackIdentityReference{ - Kind: "foobar", - Name: "foobar", - }, - }, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - warn, err := tt.template.ValidateCreate() - if tt.wantErr { - g.Expect(err).To(HaveOccurred()) - } else { - g.Expect(err).NotTo(HaveOccurred()) - } - // Nothing emits warnings yet - g.Expect(warn).To(BeEmpty()) - }) - } -} diff --git a/api/v1alpha7/openstackclustertemplate_conversion.go b/api/v1alpha7/openstackclustertemplate_conversion.go new file mode 100644 index 0000000000..1cf6e69907 --- /dev/null +++ b/api/v1alpha7/openstackclustertemplate_conversion.go @@ -0,0 +1,88 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha7 + +import ( + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" +) + +var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{} + +func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterTemplate) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate, Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, + v1alpha7OpenStackClusterTemplateRestorer, v1beta1OpenStackClusterTemplateRestorer, + ) +} + +func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterTemplate) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate, + v1beta1OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackClusterTemplateList{} + +func (r *OpenStackClusterTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackClusterTemplateList) + return Convert_v1alpha7_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(r, dst, nil) +} + +func (r *OpenStackClusterTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackClusterTemplateList) + return Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(src, r, nil) +} + +/* Restorers */ + +var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackClusterTemplate) *OpenStackClusterTemplateSpec { + return &c.Spec + }, + restorev1alpha7ClusterTemplateSpec, + ), +} + +var v1beta1OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackClusterTemplate) *infrav1.OpenStackClusterTemplateSpec { + return &c.Spec + }, + restorev1beta1ClusterTemplateSpec, + ), +} + +func restorev1alpha7ClusterTemplateSpec(previous *OpenStackClusterTemplateSpec, dst *OpenStackClusterTemplateSpec) { + restorev1alpha7ClusterSpec(&previous.Template.Spec, &dst.Template.Spec) + restorev1alpha7Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion) +} + +func restorev1beta1ClusterTemplateSpec(previous *infrav1.OpenStackClusterTemplateSpec, dst *infrav1.OpenStackClusterTemplateSpec) { + restorev1beta1Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion) + restorev1beta1ClusterSpec(&previous.Template.Spec, &dst.Template.Spec) +} diff --git a/api/v1alpha7/openstackclustertemplate_types.go b/api/v1alpha7/openstackclustertemplate_types.go index c255284a77..1c9a41b206 100644 --- a/api/v1alpha7/openstackclustertemplate_types.go +++ b/api/v1alpha7/openstackclustertemplate_types.go @@ -30,9 +30,10 @@ type OpenStackClusterTemplateSpec struct { Template OpenStackClusterTemplateResource `json:"template"` } -//+kubebuilder:object:root=true -// +kubebuilder:storageversion -//+kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct +// +genclient +// +genclient:Namespaced +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct // OpenStackClusterTemplate is the Schema for the openstackclustertemplates API. type OpenStackClusterTemplate struct { diff --git a/api/v1alpha7/openstackclustertemplate_webhook.go b/api/v1alpha7/openstackclustertemplate_webhook.go deleted file mode 100644 index 337928a3f1..0000000000 --- a/api/v1alpha7/openstackclustertemplate_webhook.go +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "fmt" - "reflect" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" -) - -const openStackClusterTemplateImmutableMsg = "OpenStackClusterTemplate spec.template.spec field is immutable. Please create new resource instead." - -func (r *OpenStackClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1alpha7,name=default.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 -// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1alpha7,name=validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 - -var ( - _ webhook.Defaulter = &OpenStackClusterTemplate{} - _ webhook.Validator = &OpenStackClusterTemplate{} -) - -// Default implements webhook.Defaulter so a webhook will be registered for the type. -func (r *OpenStackClusterTemplate) Default() { - if r.Spec.Template.Spec.IdentityRef != nil && r.Spec.Template.Spec.IdentityRef.Kind == "" { - r.Spec.Template.Spec.IdentityRef.Kind = defaultIdentityRefKind - } -} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackClusterTemplate) ValidateCreate() (admission.Warnings, error) { - var allErrs field.ErrorList - - if r.Spec.Template.Spec.IdentityRef != nil && r.Spec.Template.Spec.IdentityRef.Kind != defaultIdentityRefKind { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "template", "spec", "identityRef", "kind"), "must be a Secret")) - } - - return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackClusterTemplate) ValidateUpdate(oldRaw runtime.Object) (admission.Warnings, error) { - var allErrs field.ErrorList - old, ok := oldRaw.(*OpenStackClusterTemplate) - if !ok { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackClusterTemplate but got a %T", oldRaw)) - } - - if !reflect.DeepEqual(r.Spec.Template.Spec, old.Spec.Template.Spec) { - allErrs = append(allErrs, - field.Invalid(field.NewPath("OpenStackClusterTemplate", "spec", "template", "spec"), r, openStackClusterTemplateImmutableMsg), - ) - } - - return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackClusterTemplate) ValidateDelete() (admission.Warnings, error) { - return nil, nil -} diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go new file mode 100644 index 0000000000..5183b3fae2 --- /dev/null +++ b/api/v1alpha7/openstackmachine_conversion.go @@ -0,0 +1,297 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha7 + +import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" +) + +var _ ctrlconversion.Convertible = &OpenStackMachine{} + +func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachine) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine, Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine, + v1alpha7OpenStackMachineRestorer, v1beta1OpenStackMachineRestorer, + ) +} + +func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachine) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine, + v1beta1OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackMachineList{} + +func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachineList) + return Convert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(r, dst, nil) +} + +func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachineList) + return Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(src, r, nil) +} + +/* Restorers */ + +var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackMachine) *OpenStackMachineSpec { + return &c.Spec + }, + restorev1alpha7MachineSpec, + conversion.HashedFilterField[*OpenStackMachine, OpenStackMachineSpec](func(s *OpenStackMachineSpec) *OpenStackMachineSpec { + // Despite being spec fields, ProviderID and InstanceID + // are both set by the machine controller. If these are + // the only changes to the spec, we still want to + // restore the rest of the spec to its original state. + if s.ProviderID != nil || s.InstanceID != nil { + f := *s + f.ProviderID = nil + f.InstanceID = nil + return &f + } + return s + }), + ), +} + +var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{ + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec { + return &c.Spec + }, + restorev1beta1MachineSpec, + ), + "depresources": conversion.UnconditionalFieldRestorer( + func(c *infrav1.OpenStackMachine) **infrav1.MachineResources { + return &c.Status.Resources + }, + ), + // No equivalent in v1alpha7 + "refresources": conversion.UnconditionalFieldRestorer( + func(c *infrav1.OpenStackMachine) **infrav1.ResolvedMachineSpec { + return &c.Status.Resolved + }, + ), +} + +/* OpenStackMachine */ + +func Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *infrav1.OpenStackMachine, s apiconversion.Scope) error { + err := autoConvert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s) + if err != nil { + return err + } + + out.Status.InstanceID = in.Spec.InstanceID + return nil +} + +func Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *infrav1.OpenStackMachine, out *OpenStackMachine, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s) + if err != nil { + return err + } + + out.Spec.InstanceID = in.Status.InstanceID + return nil +} + +/* OpenStackMachineSpec */ + +func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) { + dst.FloatingIP = previous.FloatingIP + + // Conversion to v1beta1 truncates keys and values to 255 characters + for k, v := range previous.ServerMetadata { + kd := k + if len(k) > 255 { + kd = k[:255] + } + + vd := v + if len(v) > 255 { + vd = v[:255] + } + + if kd != k || vd != v { + if dst.ServerMetadata == nil { + dst.ServerMetadata = make(map[string]string) + } + delete(dst.ServerMetadata, kd) + dst.ServerMetadata[k] = v + } + } + + // Conversion to v1beta1 removes the Kind field + dst.IdentityRef = previous.IdentityRef + + if len(dst.Ports) == len(previous.Ports) { + for i := range dst.Ports { + restorev1alpha7Port(&previous.Ports[i], &dst.Ports[i]) + } + } + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for i := range dst.SecurityGroups { + restorev1alpha7SecurityGroupFilter(&previous.SecurityGroups[i], &dst.SecurityGroups[i]) + } + } + + // Conversion to v1beta1 removes Image when ImageUUID is set + if dst.Image == "" && previous.Image != "" { + dst.Image = previous.Image + } +} + +func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) { + if previous == nil || dst == nil { + return + } + + dst.ServerGroup = previous.ServerGroup + dst.Image = previous.Image + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for i := range dst.SecurityGroups { + restorev1beta1SecurityGroupParam(&previous.SecurityGroups[i], &dst.SecurityGroups[i]) + } + } + + if len(dst.Ports) == len(previous.Ports) { + for i := range dst.Ports { + restorev1beta1Port(&previous.Ports[i], &dst.Ports[i]) + } + } + dst.FloatingIPPoolRef = previous.FloatingIPPoolRef + + if dst.RootVolume != nil && previous.RootVolume != nil { + restorev1beta1BlockDeviceVolume( + &previous.RootVolume.BlockDeviceVolume, + &dst.RootVolume.BlockDeviceVolume, + ) + } + + if len(dst.AdditionalBlockDevices) == len(previous.AdditionalBlockDevices) { + for i := range dst.AdditionalBlockDevices { + restorev1beta1BlockDeviceVolume( + previous.AdditionalBlockDevices[i].Storage.Volume, + dst.AdditionalBlockDevices[i].Storage.Volume, + ) + } + } +} + +func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in, out, s) + if err != nil { + return err + } + + if in.ServerGroupID != "" { + out.ServerGroup = &infrav1.ServerGroupParam{ID: &in.ServerGroupID} + } else { + out.ServerGroup = nil + } + + imageParam := infrav1.ImageParam{} + if in.ImageUUID != "" { + imageParam.ID = &in.ImageUUID + } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both. + imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image} + } + out.Image = imageParam + + if len(in.ServerMetadata) > 0 { + serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata)) + for k, v := range in.ServerMetadata { + // Truncate key and value to 255 characters if required, as this + // was not validated prior to v1beta1 + if len(k) > 255 { + k = k[:255] + } + if len(v) > 255 { + v = v[:255] + } + + serverMetadata = append(serverMetadata, infrav1.ServerMetadata{Key: k, Value: v}) + } + out.ServerMetadata = serverMetadata + } + + if in.CloudName != "" { + if out.IdentityRef == nil { + out.IdentityRef = &infrav1.OpenStackIdentityReference{} + } + out.IdentityRef.CloudName = in.CloudName + } + + return nil +} + +func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error { + err := autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s) + if err != nil { + return err + } + + if in.ServerGroup != nil && in.ServerGroup.ID != nil { + out.ServerGroupID = *in.ServerGroup.ID + } + + if in.Image.ID != nil { + out.ImageUUID = *in.Image.ID + } else if in.Image.Filter != nil && in.Image.Filter.Name != nil { + out.Image = *in.Image.Filter.Name + } + + if len(in.ServerMetadata) > 0 { + serverMetadata := make(map[string]string, len(in.ServerMetadata)) + for i := range in.ServerMetadata { + key := in.ServerMetadata[i].Key + value := in.ServerMetadata[i].Value + serverMetadata[key] = value + } + out.ServerMetadata = serverMetadata + } + + if in.IdentityRef != nil { + out.CloudName = in.IdentityRef.CloudName + } + + return nil +} + +/* OpenStackMachineStatus */ + +func Convert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error { + // ReferencedResources have no equivalent in v1alpha7 + return autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s) +} diff --git a/api/v1alpha7/openstackmachine_types.go b/api/v1alpha7/openstackmachine_types.go index f5f4f698aa..043359db7a 100644 --- a/api/v1alpha7/openstackmachine_types.go +++ b/api/v1alpha7/openstackmachine_types.go @@ -19,7 +19,7 @@ package v1alpha7 import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/errors" ) @@ -93,7 +93,8 @@ type OpenStackMachineSpec struct { // The server group to assign the machine to ServerGroupID string `json:"serverGroupID,omitempty"` - // IdentityRef is a reference to a identity to be used when reconciling this cluster + // IdentityRef is a reference to a identity to be used when reconciling this cluster. + // If not specified, the identity ref of the cluster will be used instead. // +optional IdentityRef *OpenStackIdentityReference `json:"identityRef,omitempty"` } @@ -135,8 +136,9 @@ type OpenStackMachineStatus struct { Conditions clusterv1.Conditions `json:"conditions,omitempty"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true -// +kubebuilder:storageversion // +kubebuilder:resource:path=openstackmachines,scope=Namespaced,categories=cluster-api,shortName=osm // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this OpenStackMachine belongs" @@ -177,7 +179,7 @@ func (r *OpenStackMachine) SetConditions(conditions clusterv1.Conditions) { // SetFailure sets the OpenStackMachine status failure reason and failure message. func (r *OpenStackMachine) SetFailure(failureReason errors.MachineStatusError, failureMessage error) { r.Status.FailureReason = &failureReason - r.Status.FailureMessage = pointer.String(failureMessage.Error()) + r.Status.FailureMessage = ptr.To(failureMessage.Error()) } func init() { diff --git a/api/v1alpha7/openstackmachine_webhook.go b/api/v1alpha7/openstackmachine_webhook.go deleted file mode 100644 index 6470589a76..0000000000 --- a/api/v1alpha7/openstackmachine_webhook.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "fmt" - "reflect" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - "sigs.k8s.io/controller-runtime/pkg/builder" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" -) - -// log is for logging in this package. -var _ = logf.Log.WithName("openstackmachine-resource") - -func (r *OpenStackMachine) SetupWebhookWithManager(mgr manager.Manager) error { - return builder.WebhookManagedBy(mgr). - For(r). - Complete() -} - -// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1alpha7,name=validation.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 -// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1alpha7,name=default.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 - -var ( - _ webhook.Defaulter = &OpenStackMachine{} - _ webhook.Validator = &OpenStackMachine{} -) - -// Default satisfies the defaulting webhook interface. -func (r *OpenStackMachine) Default() { - if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind == "" { - r.Spec.IdentityRef.Kind = defaultIdentityRefKind - } -} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackMachine) ValidateCreate() (admission.Warnings, error) { - var allErrs field.ErrorList - - if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind != defaultIdentityRefKind { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "identityRef", "kind"), "must be a Secret")) - } - - if r.Spec.RootVolume != nil && r.Spec.AdditionalBlockDevices != nil { - for _, device := range r.Spec.AdditionalBlockDevices { - if device.Name == "root" { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "additionalBlockDevices"), "cannot contain a device named \"root\" when rootVolume is set")) - } - } - } - - return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackMachine) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - newOpenStackMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r) - if err != nil { - return nil, apierrors.NewInvalid(GroupVersion.WithKind("OpenStackMachine").GroupKind(), r.Name, field.ErrorList{ - field.InternalError(nil, fmt.Errorf("failed to convert new OpenStackMachine to unstructured object: %w", err)), - }) - } - oldOpenStackMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(old) - if err != nil { - return nil, apierrors.NewInvalid(GroupVersion.WithKind("OpenStackMachine").GroupKind(), r.Name, field.ErrorList{ - field.InternalError(nil, fmt.Errorf("failed to convert old OpenStackMachine to unstructured object: %w", err)), - }) - } - - var allErrs field.ErrorList - - if r.Spec.IdentityRef != nil && r.Spec.IdentityRef.Kind != defaultIdentityRefKind { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "identityRef", "kind"), "must be a Secret")) - } - - newOpenStackMachineSpec := newOpenStackMachine["spec"].(map[string]interface{}) - oldOpenStackMachineSpec := oldOpenStackMachine["spec"].(map[string]interface{}) - - // allow changes to providerID once - if oldOpenStackMachineSpec["providerID"] == nil { - delete(oldOpenStackMachineSpec, "providerID") - delete(newOpenStackMachineSpec, "providerID") - } - - // allow changes to instanceID once - if oldOpenStackMachineSpec["instanceID"] == nil { - delete(oldOpenStackMachineSpec, "instanceID") - delete(newOpenStackMachineSpec, "instanceID") - } - - if !reflect.DeepEqual(oldOpenStackMachineSpec, newOpenStackMachineSpec) { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified")) - } - - return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs) -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *OpenStackMachine) ValidateDelete() (admission.Warnings, error) { - return nil, nil -} diff --git a/api/v1alpha7/openstackmachinetemplate_conversion.go b/api/v1alpha7/openstackmachinetemplate_conversion.go new file mode 100644 index 0000000000..62ee4739a1 --- /dev/null +++ b/api/v1alpha7/openstackmachinetemplate_conversion.go @@ -0,0 +1,89 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha7 + +import ( + ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion" +) + +var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{} + +func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachineTemplate) + + return conversion.ConvertAndRestore( + r, dst, + Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate, Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, + v1alpha7OpenStackMachineTemplateRestorer, v1beta1OpenStackMachineTemplateRestorer, + ) +} + +func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachineTemplate) + + return conversion.ConvertAndRestore( + src, r, + Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate, + v1beta1OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer, + ) +} + +var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{} + +func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error { + dst := dstRaw.(*infrav1.OpenStackMachineTemplateList) + return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(r, dst, nil) +} + +func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error { + src := srcRaw.(*infrav1.OpenStackMachineTemplateList) + return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(src, r, nil) +} + +/* Restorers */ + +var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *OpenStackMachineTemplate) *OpenStackMachineTemplateSpec { + return &c.Spec + }, + restorev1alpha7MachineTemplateSpec, + ), +} + +var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{ + "spec": conversion.HashedFieldRestorer( + func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec { + return &c.Spec.Template.Spec + }, + restorev1beta1MachineSpec, + ), +} + +func restorev1alpha7MachineTemplateSpec(previous *OpenStackMachineTemplateSpec, dst *OpenStackMachineTemplateSpec) { + if previous == nil || dst == nil { + return + } + + prevMachineSpec := &previous.Template.Spec + dstMachineSpec := &dst.Template.Spec + restorev1alpha7MachineSpec(prevMachineSpec, dstMachineSpec) + dstMachineSpec.InstanceID = prevMachineSpec.InstanceID +} diff --git a/api/v1alpha7/openstackmachinetemplate_types.go b/api/v1alpha7/openstackmachinetemplate_types.go index 5202234ba2..dc0eb97c07 100644 --- a/api/v1alpha7/openstackmachinetemplate_types.go +++ b/api/v1alpha7/openstackmachinetemplate_types.go @@ -25,8 +25,9 @@ type OpenStackMachineTemplateSpec struct { Template OpenStackMachineTemplateResource `json:"template"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true -// +kubebuilder:storageversion // +kubebuilder:resource:path=openstackmachinetemplates,scope=Namespaced,categories=cluster-api,shortName=osmt // OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API. diff --git a/api/v1alpha7/openstackmachinetemplate_webhook.go b/api/v1alpha7/openstackmachinetemplate_webhook.go deleted file mode 100644 index b74d056ba2..0000000000 --- a/api/v1alpha7/openstackmachinetemplate_webhook.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "context" - "fmt" - "reflect" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - "sigs.k8s.io/cluster-api/util/topology" - "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" -) - -// OpenStackMachineTemplateImmutableMsg ... -const OpenStackMachineTemplateImmutableMsg = "OpenStackMachineTemplate spec.template.spec field is immutable. Please create a new resource instead. Ref doc: https://cluster-api.sigs.k8s.io/tasks/change-machine-template.html" - -// +kubebuilder:object:generate=false -type OpenStackMachineTemplateWebhook struct{} - -func (r *OpenStackMachineTemplateWebhook) SetupWebhookWithManager(mgr manager.Manager) error { - return builder.WebhookManagedBy(mgr). - For(&OpenStackMachineTemplate{}). - WithValidator(r). - Complete() -} - -// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachinetemplates,versions=v1alpha7,name=validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1 - -var _ webhook.CustomValidator = &OpenStackMachineTemplateWebhook{} - -// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type. -func (r *OpenStackMachineTemplateWebhook) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { - openStackMachineTemplate, ok := obj.(*OpenStackMachineTemplate) - if !ok { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackMachineTemplate but got a %T", obj)) - } - - var allErrs field.ErrorList - - if openStackMachineTemplate.Spec.Template.Spec.ProviderID != nil { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "template", "spec", "providerID"), "cannot be set in templates")) - } - - return aggregateObjErrors(openStackMachineTemplate.GroupVersionKind().GroupKind(), openStackMachineTemplate.Name, allErrs) -} - -// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type. -func (r *OpenStackMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw runtime.Object, newRaw runtime.Object) (admission.Warnings, error) { - var allErrs field.ErrorList - old, ok := oldRaw.(*OpenStackMachineTemplate) - if !ok { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackMachineTemplate but got a %T", oldRaw)) - } - - newObj, ok := newRaw.(*OpenStackMachineTemplate) - if !ok { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackMachineTemplate but got a %T", oldRaw)) - } - - req, err := admission.RequestFromContext(ctx) - if err != nil { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a admission.Request inside context: %v", err)) - } - - if !topology.ShouldSkipImmutabilityChecks(req, newObj) && - !reflect.DeepEqual(newObj.Spec.Template.Spec, old.Spec.Template.Spec) { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec", "template", "spec"), r, OpenStackMachineTemplateImmutableMsg), - ) - } - - return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs) -} - -// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type. -func (r *OpenStackMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { - return nil, nil -} diff --git a/api/v1alpha7/openstackmachinetemplate_webhook_test.go b/api/v1alpha7/openstackmachinetemplate_webhook_test.go deleted file mode 100644 index d9a53adc17..0000000000 --- a/api/v1alpha7/openstackmachinetemplate_webhook_test.go +++ /dev/null @@ -1,170 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha7 - -import ( - "context" - "testing" - - . "github.com/onsi/gomega" - admissionv1 "k8s.io/api/admission/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" - clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" -) - -func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { - g := NewWithT(t) - - tests := []struct { - name string - oldTemplate *OpenStackMachineTemplate - newTemplate *OpenStackMachineTemplate - req *admission.Request - wantErr bool - }{ - { - name: "OpenStackMachineTemplate with immutable spec", - oldTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "bar", - }, - }, - }, - }, - newTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "NewImage", - }, - }, - }, - }, - req: &admission.Request{}, - wantErr: true, - }, - { - name: "OpenStackMachineTemplate with mutable metadata", - oldTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "bar", - }, - }, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - }, - newTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "bar", - }, - }, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "bar", - }, - }, - req: &admission.Request{}, - }, - { - name: "don't allow modification, dry run, no skip immutability annotation set", - oldTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "bar", - }, - }, - }, - }, - newTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "NewImage", - }, - }, - }, - }, - req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: pointer.Bool(true)}}, - wantErr: true, - }, - { - name: "allow modification, dry run, skip immutability annotation set", - oldTemplate: &OpenStackMachineTemplate{ - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "bar", - }, - }, - }, - }, - newTemplate: &OpenStackMachineTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - clusterv1.TopologyDryRunAnnotation: "", - }, - }, - Spec: OpenStackMachineTemplateSpec{ - Template: OpenStackMachineTemplateResource{ - Spec: OpenStackMachineSpec{ - Flavor: "foo", - Image: "NewImage", - }, - }, - }, - }, - req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: pointer.Bool(true)}}, - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - webhook := &OpenStackMachineTemplateWebhook{} - ctx := admission.NewContextWithRequest(context.Background(), *tt.req) - - warn, err := webhook.ValidateUpdate(ctx, tt.oldTemplate, tt.newTemplate) - if tt.wantErr { - g.Expect(err).To(HaveOccurred()) - } else { - g.Expect(err).NotTo(HaveOccurred()) - } - // Nothing emits warnings yet - g.Expect(warn).To(BeEmpty()) - }) - } -} diff --git a/api/v1alpha7/types.go b/api/v1alpha7/types.go index 3ef5305ff2..c9404cec70 100644 --- a/api/v1alpha7/types.go +++ b/api/v1alpha7/types.go @@ -281,7 +281,7 @@ type LoadBalancer struct { type SecurityGroup struct { Name string `json:"name"` ID string `json:"id"` - Rules []SecurityGroupRule `json:"rules"` + Rules []SecurityGroupRule `json:"rules,omitempty"` } // SecurityGroupRule represent the basic information of the associated OpenStack @@ -315,8 +315,8 @@ func (r SecurityGroupRule) Equal(x SecurityGroupRule) bool { type InstanceState string var ( - // InstanceStateBuilding is the string representing an instance in a building state. - InstanceStateBuilding = InstanceState("BUILDING") + // InstanceStateBuild is the string representing an instance in a build state. + InstanceStateBuild = InstanceState("BUILD") // InstanceStateActive is the string representing an instance in an active state. InstanceStateActive = InstanceState("ACTIVE") @@ -332,6 +332,9 @@ var ( // InstanceStateDeleted is the string representing an instance in a deleted state. InstanceStateDeleted = InstanceState("DELETED") + + // InstanceStateUndefined is the string representing an undefined instance state. + InstanceStateUndefined = InstanceState("") ) // Bastion represents basic information about the bastion node. diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go new file mode 100644 index 0000000000..806e145806 --- /dev/null +++ b/api/v1alpha7/types_conversion.go @@ -0,0 +1,588 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha7 + +import ( + "errors" + + apiconversion "k8s.io/apimachinery/pkg/conversion" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversioncommon" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" +) + +/* SecurityGroupFilter */ + +func restorev1alpha7SecurityGroupFilter(previous *SecurityGroupFilter, dst *SecurityGroupFilter) { + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny + + // If ID was set we lost all other filter params + if dst.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + } +} + +func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) { + if previous == nil || dst == nil { + return + } + + dst.Rules = previous.Rules +} + +func restorev1beta1SecurityGroupParam(previous *infrav1.SecurityGroupParam, dst *infrav1.SecurityGroupParam) { + if previous == nil || dst == nil { + return + } + + if dst.Filter != nil && previous.Filter != nil { + dst.Filter.Tags = previous.Filter.Tags + dst.Filter.TagsAny = previous.Filter.TagsAny + dst.Filter.NotTags = previous.Filter.NotTags + dst.Filter.NotTagsAny = previous.Filter.NotTagsAny + } +} + +func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(in *SecurityGroupFilter, out *infrav1.SecurityGroupParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + + filter := &infrav1.SecurityGroupFilter{} + if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, filter, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags) + if !filter.IsZero() { + out.Filter = filter + } + return nil +} + +func Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupParam, out *SecurityGroupFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + + if in.Filter != nil { + if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + } + return nil +} + +/* NetworkFilter */ + +func restorev1alpha7NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) { + if previous == nil || dst == nil { + return + } + + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny + + // If ID was set we lost all over filter params + if dst.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + } +} + +func restorev1beta1NetworkParam(previous *infrav1.NetworkParam, dst *infrav1.NetworkParam) { + if previous == nil || dst == nil { + return + } + + if dst.Filter != nil && previous.Filter != nil { + dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags + } +} + +func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkParam(in *NetworkFilter, out *infrav1.NetworkParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + outFilter := &infrav1.NetworkFilter{} + if err := autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, outFilter, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &outFilter.FilterByNeutronTags) + if !outFilter.IsZero() { + out.Filter = outFilter + } + return nil +} + +func Convert_v1beta1_NetworkParam_To_v1alpha7_NetworkFilter(in *infrav1.NetworkParam, out *NetworkFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + + if in.Filter != nil { + if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + } + return nil +} + +/* SubnetFilter */ + +func restorev1alpha7SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) { + if previous == nil || dst == nil { + return + } + + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny + + // If ID was set we will have lost all other fields in up-conversion + if previous.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + dst.IPVersion = previous.IPVersion + dst.GatewayIP = previous.GatewayIP + dst.CIDR = previous.CIDR + dst.IPv6AddressMode = previous.IPv6AddressMode + dst.IPv6RAMode = previous.IPv6RAMode + } +} + +func restorev1beta1SubnetParam(previous *infrav1.SubnetParam, dst *infrav1.SubnetParam) { + if previous == nil || dst == nil { + return + } + + optional.RestoreString(&previous.ID, &dst.ID) + + if previous.Filter != nil && dst.Filter != nil { + dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags + } +} + +func Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(in *SubnetFilter, out *infrav1.SubnetParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + + filter := &infrav1.SubnetFilter{} + if err := autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in, filter, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags) + + if !filter.IsZero() { + out.Filter = filter + } + return nil +} + +func Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(in *infrav1.SubnetParam, out *SubnetFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + + if in.Filter == nil { + return nil + } + + if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + return nil +} + +/* RouterFilter */ + +func restorev1alpha7RouterFilter(previous *RouterFilter, dst *RouterFilter) { + // The edge cases with multiple commas are too tricky in this direction, + // so we just restore the whole thing. + dst.Tags = previous.Tags + dst.TagsAny = previous.TagsAny + dst.NotTags = previous.NotTags + dst.NotTagsAny = previous.NotTagsAny + + // If ID was set we lost all other filter params + if dst.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + } +} + +func restorev1beta1RouterParam(previous *infrav1.RouterParam, dst *infrav1.RouterParam) { + if previous == nil || dst == nil { + return + } + + optional.RestoreString(&previous.ID, &dst.ID) + if previous.Filter != nil && dst.Filter != nil { + dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags + } +} + +func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterParam(in *RouterFilter, out *infrav1.RouterParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + + filter := &infrav1.RouterFilter{} + if err := autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, filter, s); err != nil { + return err + } + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags) + if !filter.IsZero() { + out.Filter = filter + } + return nil +} + +func Convert_v1beta1_RouterParam_To_v1alpha7_RouterFilter(in *infrav1.RouterParam, out *RouterFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + + if in.Filter != nil { + if err := autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) + } + return nil +} + +/* PortOpts */ + +func restorev1alpha7Port(previous *PortOpts, dst *PortOpts) { + if len(dst.SecurityGroupFilters) == len(previous.SecurityGroupFilters) { + for i := range dst.SecurityGroupFilters { + restorev1alpha7SecurityGroupFilter(&previous.SecurityGroupFilters[i], &dst.SecurityGroupFilters[i]) + } + } + + if dst.Network != nil && previous.Network != nil { + restorev1alpha7NetworkFilter(previous.Network, dst.Network) + } + + if len(dst.FixedIPs) == len(previous.FixedIPs) { + for i := range dst.FixedIPs { + prevFixedIP := &previous.FixedIPs[i] + dstFixedIP := &dst.FixedIPs[i] + + if dstFixedIP.Subnet != nil && prevFixedIP.Subnet != nil { + restorev1alpha7SubnetFilter(prevFixedIP.Subnet, dstFixedIP.Subnet) + } + } + } +} + +func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) { + restorev1beta1NetworkParam(previous.Network, dst.Network) + + optional.RestoreString(&previous.NameSuffix, &dst.NameSuffix) + optional.RestoreString(&previous.Description, &dst.Description) + optional.RestoreString(&previous.MACAddress, &dst.MACAddress) + + if len(dst.FixedIPs) == len(previous.FixedIPs) { + for j := range dst.FixedIPs { + prevFixedIP := &previous.FixedIPs[j] + dstFixedIP := &dst.FixedIPs[j] + + optional.RestoreString(&prevFixedIP.IPAddress, &dstFixedIP.IPAddress) + restorev1beta1SubnetParam(prevFixedIP.Subnet, dstFixedIP.Subnet) + } + } + + if len(dst.AllowedAddressPairs) == len(previous.AllowedAddressPairs) { + for j := range dst.AllowedAddressPairs { + prevAAP := &previous.AllowedAddressPairs[j] + dstAAP := &dst.AllowedAddressPairs[j] + + optional.RestoreString(&prevAAP.MACAddress, &dstAAP.MACAddress) + } + } + + optional.RestoreString(&previous.HostID, &dst.HostID) + optional.RestoreString(&previous.VNICType, &dst.VNICType) + + if dst.Profile == nil && previous.Profile != nil { + dst.Profile = &infrav1.BindingProfile{} + } + + if dst.Profile != nil && previous.Profile != nil { + dstProfile := dst.Profile + prevProfile := previous.Profile + + if dstProfile.OVSHWOffload == nil || !*dstProfile.OVSHWOffload { + dstProfile.OVSHWOffload = prevProfile.OVSHWOffload + } + + if dstProfile.TrustedVF == nil || !*dstProfile.TrustedVF { + dstProfile.TrustedVF = prevProfile.TrustedVF + } + } + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for j := range dst.SecurityGroups { + restorev1beta1SecurityGroupParam(&previous.SecurityGroups[j], &dst.SecurityGroups[j]) + } + } +} + +func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error { + if err := autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in, out, s); err != nil { + return err + } + + // Copy members of ResolvedPortSpecFields + var allowedAddressPairs []infrav1.AddressPair + if len(in.AllowedAddressPairs) > 0 { + allowedAddressPairs = make([]infrav1.AddressPair, len(in.AllowedAddressPairs)) + for i := range in.AllowedAddressPairs { + aap := &in.AllowedAddressPairs[i] + allowedAddressPairs[i] = infrav1.AddressPair{ + MACAddress: &aap.MACAddress, + IPAddress: aap.IPAddress, + } + } + } + var valueSpecs []infrav1.ValueSpec + if len(in.ValueSpecs) > 0 { + valueSpecs = make([]infrav1.ValueSpec, len(in.ValueSpecs)) + for i, vs := range in.ValueSpecs { + valueSpecs[i] = infrav1.ValueSpec(vs) + } + } + out.AdminStateUp = in.AdminStateUp + out.AllowedAddressPairs = allowedAddressPairs + out.DisablePortSecurity = in.DisablePortSecurity + out.PropagateUplinkStatus = in.PropagateUplinkStatus + out.ValueSpecs = valueSpecs + if err := errors.Join( + optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s), + optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s), + optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s), + ); err != nil { + return err + } + + if len(in.SecurityGroupFilters) > 0 { + out.SecurityGroups = make([]infrav1.SecurityGroupParam, len(in.SecurityGroupFilters)) + for i := range in.SecurityGroupFilters { + if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil { + return err + } + } + } + + if in.Profile != (BindingProfile{}) { + out.Profile = &infrav1.BindingProfile{} + if err := Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(&in.Profile, out.Profile, s); err != nil { + return err + } + } + + return nil +} + +func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error { + if err := autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in, out, s); err != nil { + return err + } + + // Copy members of ResolvedPortSpecFields + var allowedAddressPairs []AddressPair + if len(in.AllowedAddressPairs) > 0 { + allowedAddressPairs = make([]AddressPair, len(in.AllowedAddressPairs)) + for i := range in.AllowedAddressPairs { + inAAP := &in.AllowedAddressPairs[i] + outAAP := &allowedAddressPairs[i] + if err := optional.Convert_optional_String_To_string(&inAAP.MACAddress, &outAAP.MACAddress, s); err != nil { + return err + } + outAAP.IPAddress = inAAP.IPAddress + } + } + var valueSpecs []ValueSpec + if len(in.ValueSpecs) > 0 { + valueSpecs = make([]ValueSpec, len(in.ValueSpecs)) + for i, vs := range in.ValueSpecs { + valueSpecs[i] = ValueSpec(vs) + } + } + out.AdminStateUp = in.AdminStateUp + out.AllowedAddressPairs = allowedAddressPairs + out.DisablePortSecurity = in.DisablePortSecurity + out.PropagateUplinkStatus = in.PropagateUplinkStatus + out.ValueSpecs = valueSpecs + if err := errors.Join( + optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s), + optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s), + optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s), + ); err != nil { + return err + } + + if len(in.SecurityGroups) > 0 { + out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups)) + for i := range in.SecurityGroups { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { + return err + } + } + } + + if in.Profile != nil { + if err := Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in.Profile, &out.Profile, s); err != nil { + return err + } + } + + return nil +} + +/* RootVolume */ + +func restorev1beta1BlockDeviceVolume(previous *infrav1.BlockDeviceVolume, dst *infrav1.BlockDeviceVolume) { + if previous == nil || dst == nil { + return + } + + dstAZ := dst.AvailabilityZone + previousAZ := previous.AvailabilityZone + + // Empty From (the default) will be converted to the explicit "Name" + if dstAZ != nil && previousAZ != nil && dstAZ.From == "Name" { + dstAZ.From = previousAZ.From + } +} + +func Convert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *infrav1.RootVolume, s apiconversion.Scope) error { + out.SizeGiB = in.Size + out.Type = in.VolumeType + return conversioncommon.Convert_string_To_Pointer_v1beta1_VolumeAvailabilityZone(&in.AvailabilityZone, &out.AvailabilityZone, s) +} + +func Convert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in *infrav1.RootVolume, out *RootVolume, s apiconversion.Scope) error { + out.Size = in.SizeGiB + out.VolumeType = in.Type + return conversioncommon.Convert_Pointer_v1beta1_VolumeAvailabilityZone_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s) +} + +/* SecurityGroup */ + +func Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, _ apiconversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + + return nil +} + +func Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, _ apiconversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + return nil +} + +/* OpenStackIdentityReference */ + +func Convert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error { + return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in, out, s) +} + +func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *infrav1.OpenStackIdentityReference, out *OpenStackIdentityReference, _ apiconversion.Scope) error { + out.Name = in.Name + return nil +} + +/* APIServerLoadBalancer */ + +func restorev1beta1APIServerLoadBalancer(previous *infrav1.APIServerLoadBalancer, dst *infrav1.APIServerLoadBalancer) { + if dst == nil || previous == nil { + return + } + + // AZ doesn't exist in v1alpha6, so always restore. + dst.AvailabilityZone = previous.AvailabilityZone +} + +/* Placeholders */ + +// conversion-gen registers these functions so we must provider stubs, but +// nothing should ever call them + +func Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(_ *SubnetFilter, _ *infrav1.SubnetFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter should not be called") +} + +func Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(_ *infrav1.SubnetFilter, _ *SubnetFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter should not be called") +} + +func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(_ *NetworkFilter, _ *infrav1.NetworkFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter should not be called") +} + +func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(_ *infrav1.NetworkFilter, _ *NetworkFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter should not be called") +} + +func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(_ *SecurityGroupFilter, _ *infrav1.SecurityGroupFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter should not be called") +} + +func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(_ *infrav1.SecurityGroupFilter, _ *SecurityGroupFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter should not be called") +} + +func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(_ *RouterFilter, _ *infrav1.RouterFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter should not be called") +} + +func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(_ *infrav1.RouterFilter, _ *RouterFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter should not be called") +} diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go new file mode 100644 index 0000000000..f67c228983 --- /dev/null +++ b/api/v1alpha7/zz_generated.conversion.go @@ -0,0 +1,1902 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha7 + +import ( + unsafe "unsafe" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + conversioncommon "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversioncommon" + optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" + apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" + errors "sigs.k8s.io/cluster-api/errors" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*AdditionalBlockDevice)(nil), (*v1beta1.AdditionalBlockDevice)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice(a.(*AdditionalBlockDevice), b.(*v1beta1.AdditionalBlockDevice), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.AdditionalBlockDevice)(nil), (*AdditionalBlockDevice)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(a.(*v1beta1.AdditionalBlockDevice), b.(*AdditionalBlockDevice), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1beta1.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_AddressPair_To_v1beta1_AddressPair(a.(*AddressPair), b.(*v1beta1.AddressPair), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(a.(*v1beta1.AddressPair), b.(*AddressPair), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*BastionStatus)(nil), (*v1beta1.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus(a.(*BastionStatus), b.(*v1beta1.BastionStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*BindingProfile)(nil), (*v1beta1.BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(a.(*BindingProfile), b.(*v1beta1.BindingProfile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.BindingProfile)(nil), (*BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(a.(*v1beta1.BindingProfile), b.(*BindingProfile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*BlockDeviceStorage)(nil), (*v1beta1.BlockDeviceStorage)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(a.(*BlockDeviceStorage), b.(*v1beta1.BlockDeviceStorage), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.BlockDeviceStorage)(nil), (*BlockDeviceStorage)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(a.(*v1beta1.BlockDeviceStorage), b.(*BlockDeviceStorage), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*BlockDeviceVolume)(nil), (*v1beta1.BlockDeviceVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(a.(*BlockDeviceVolume), b.(*v1beta1.BlockDeviceVolume), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.BlockDeviceVolume)(nil), (*BlockDeviceVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(a.(*v1beta1.BlockDeviceVolume), b.(*BlockDeviceVolume), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1beta1.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1beta1.ExternalRouterIPParam), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(a.(*v1beta1.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*FixedIP)(nil), (*v1beta1.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_FixedIP_To_v1beta1_FixedIP(a.(*FixedIP), b.(*v1beta1.FixedIP), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_FixedIP_To_v1alpha7_FixedIP(a.(*v1beta1.FixedIP), b.(*FixedIP), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*LoadBalancer)(nil), (*v1beta1.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_LoadBalancer_To_v1beta1_LoadBalancer(a.(*LoadBalancer), b.(*v1beta1.LoadBalancer), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*NetworkStatus)(nil), (*v1beta1.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus(a.(*NetworkStatus), b.(*v1beta1.NetworkStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.NetworkStatus)(nil), (*NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkStatus_To_v1alpha7_NetworkStatus(a.(*v1beta1.NetworkStatus), b.(*NetworkStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*NetworkStatusWithSubnets)(nil), (*v1beta1.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_NetworkStatusWithSubnets_To_v1beta1_NetworkStatusWithSubnets(a.(*NetworkStatusWithSubnets), b.(*v1beta1.NetworkStatusWithSubnets), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.NetworkStatusWithSubnets)(nil), (*NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(a.(*v1beta1.NetworkStatusWithSubnets), b.(*NetworkStatusWithSubnets), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1beta1.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster(a.(*OpenStackCluster), b.(*v1beta1.OpenStackCluster), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(a.(*v1beta1.OpenStackCluster), b.(*OpenStackCluster), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackClusterList)(nil), (*v1beta1.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1beta1.OpenStackClusterList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(a.(*v1beta1.OpenStackClusterList), b.(*OpenStackClusterList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackClusterStatus)(nil), (*v1beta1.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1beta1.OpenStackClusterStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1beta1.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1beta1.OpenStackClusterTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(a.(*v1beta1.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateList)(nil), (*v1beta1.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1beta1.OpenStackClusterTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(a.(*v1beta1.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateResource)(nil), (*v1beta1.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1beta1.OpenStackClusterTemplateResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(a.(*v1beta1.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateSpec)(nil), (*v1beta1.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1beta1.OpenStackClusterTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(a.(*v1beta1.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1beta1.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1beta1.OpenStackMachineList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(a.(*v1beta1.OpenStackMachineList), b.(*OpenStackMachineList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1beta1.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1beta1.OpenStackMachineStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1beta1.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1beta1.OpenStackMachineTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(a.(*v1beta1.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1beta1.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1beta1.OpenStackMachineTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(a.(*v1beta1.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1beta1.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1beta1.OpenStackMachineTemplateResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(a.(*v1beta1.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1beta1.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1beta1.OpenStackMachineTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(a.(*v1beta1.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1beta1.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_Router_To_v1beta1_Router(a.(*Router), b.(*v1beta1.Router), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Router_To_v1alpha7_Router(a.(*v1beta1.Router), b.(*Router), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1beta1.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_Subnet_To_v1beta1_Subnet(a.(*Subnet), b.(*v1beta1.Subnet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Subnet_To_v1alpha7_Subnet(a.(*v1beta1.Subnet), b.(*Subnet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1beta1.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_ValueSpec_To_v1beta1_ValueSpec(a.(*ValueSpec), b.(*v1beta1.ValueSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ValueSpec_To_v1alpha7_ValueSpec(a.(*v1beta1.ValueSpec), b.(*ValueSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*APIServerLoadBalancer)(nil), (*v1beta1.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1beta1.APIServerLoadBalancer), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*Bastion)(nil), (*v1beta1.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_Bastion_To_v1beta1_Bastion(a.(*Bastion), b.(*v1beta1.Bastion), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*NetworkFilter)(nil), (*v1beta1.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(a.(*NetworkFilter), b.(*v1beta1.NetworkFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*NetworkFilter)(nil), (*v1beta1.NetworkParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkParam(a.(*NetworkFilter), b.(*v1beta1.NetworkParam), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1beta1.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1beta1.OpenStackClusterSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1beta1.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1beta1.OpenStackIdentityReference), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1beta1.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1beta1.OpenStackMachineSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*OpenStackMachine)(nil), (*v1beta1.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(a.(*OpenStackMachine), b.(*v1beta1.OpenStackMachine), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*PortOpts)(nil), (*v1beta1.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(a.(*PortOpts), b.(*v1beta1.PortOpts), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*RootVolume)(nil), (*v1beta1.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_RootVolume_To_v1beta1_RootVolume(a.(*RootVolume), b.(*v1beta1.RootVolume), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*RouterFilter)(nil), (*v1beta1.RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(a.(*RouterFilter), b.(*v1beta1.RouterFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*RouterFilter)(nil), (*v1beta1.RouterParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_RouterFilter_To_v1beta1_RouterParam(a.(*RouterFilter), b.(*v1beta1.RouterParam), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1beta1.SecurityGroupFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1beta1.SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(a.(*SecurityGroupFilter), b.(*v1beta1.SecurityGroupParam), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1beta1.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1beta1.SecurityGroupStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*SubnetFilter)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(a.(*SubnetFilter), b.(*v1beta1.SubnetFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*SubnetFilter)(nil), (*v1beta1.SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(a.(*SubnetFilter), b.(*v1beta1.SubnetParam), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(a.(*v1beta1.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.BastionStatus)(nil), (*BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(a.(*v1beta1.BastionStatus), b.(*BastionStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Bastion_To_v1alpha7_Bastion(a.(*v1beta1.Bastion), b.(*Bastion), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(a.(*v1beta1.LoadBalancer), b.(*LoadBalancer), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(a.(*v1beta1.NetworkFilter), b.(*NetworkFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.NetworkParam)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkParam_To_v1alpha7_NetworkFilter(a.(*v1beta1.NetworkParam), b.(*NetworkFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1beta1.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*v1beta1.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(a.(*v1beta1.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1beta1.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*v1beta1.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(a.(*v1beta1.OpenStackMachine), b.(*OpenStackMachine), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(a.(*v1beta1.PortOpts), b.(*PortOpts), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RootVolume_To_v1alpha7_RootVolume(a.(*v1beta1.RootVolume), b.(*RootVolume), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.RouterFilter)(nil), (*RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(a.(*v1beta1.RouterFilter), b.(*RouterFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.RouterParam)(nil), (*RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RouterParam_To_v1alpha7_RouterFilter(a.(*v1beta1.RouterParam), b.(*RouterFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(a.(*v1beta1.SecurityGroupParam), b.(*SecurityGroupFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(a.(*v1beta1.SecurityGroupStatus), b.(*SecurityGroup), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(a.(*v1beta1.SubnetFilter), b.(*SubnetFilter), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.SubnetParam)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(a.(*v1beta1.SubnetParam), b.(*SubnetFilter), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts)) + out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) + if err := optional.Convert_string_To_optional_String(&in.Provider, &out.Provider, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts)) + out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) + if err := optional.Convert_optional_String_To_string(&in.Provider, &out.Provider, s); err != nil { + return err + } + // WARNING: in.Network requires manual conversion: does not exist in peer-type + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1beta1.AdditionalBlockDevice, s conversion.Scope) error { + out.Name = in.Name + out.SizeGiB = in.SizeGiB + if err := Convert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice is an autogenerated conversion function. +func Convert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1beta1.AdditionalBlockDevice, s conversion.Scope) error { + return autoConvert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice(in, out, s) +} + +func autoConvert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in *v1beta1.AdditionalBlockDevice, out *AdditionalBlockDevice, s conversion.Scope) error { + out.Name = in.Name + out.SizeGiB = in.SizeGiB + if err := Convert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice is an autogenerated conversion function. +func Convert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in *v1beta1.AdditionalBlockDevice, out *AdditionalBlockDevice, s conversion.Scope) error { + return autoConvert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in, out, s) +} + +func autoConvert_v1alpha7_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error { + out.IPAddress = in.IPAddress + if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_AddressPair_To_v1beta1_AddressPair is an autogenerated conversion function. +func Convert_v1alpha7_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error { + return autoConvert_v1alpha7_AddressPair_To_v1beta1_AddressPair(in, out, s) +} + +func autoConvert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error { + out.IPAddress = in.IPAddress + if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair is an autogenerated conversion function. +func Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error { + return autoConvert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in, out, s) +} + +func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error { + if err := optional.Convert_bool_To_optional_Bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + // WARNING: in.Instance requires manual conversion: does not exist in peer-type + if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error { + if err := optional.Convert_optional_Bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil { + return err + } + // WARNING: in.Spec requires manual conversion: does not exist in peer-type + if err := optional.Convert_optional_String_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { + return err + } + // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus(in *BastionStatus, out *v1beta1.BastionStatus, s conversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + out.SSHKeyName = in.SSHKeyName + out.State = v1beta1.InstanceState(in.State) + out.IP = in.IP + out.FloatingIP = in.FloatingIP + return nil +} + +// Convert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus is an autogenerated conversion function. +func Convert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus(in *BastionStatus, out *v1beta1.BastionStatus, s conversion.Scope) error { + return autoConvert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus(in, out, s) +} + +func autoConvert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *v1beta1.BastionStatus, out *BastionStatus, s conversion.Scope) error { + out.ID = in.ID + out.Name = in.Name + out.SSHKeyName = in.SSHKeyName + out.State = InstanceState(in.State) + out.IP = in.IP + out.FloatingIP = in.FloatingIP + // WARNING: in.Resolved requires manual conversion: does not exist in peer-type + // WARNING: in.Resources requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(in *BindingProfile, out *v1beta1.BindingProfile, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.OVSHWOffload, &out.OVSHWOffload, s); err != nil { + return err + } + if err := v1.Convert_bool_To_Pointer_bool(&in.TrustedVF, &out.TrustedVF, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile is an autogenerated conversion function. +func Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(in *BindingProfile, out *v1beta1.BindingProfile, s conversion.Scope) error { + return autoConvert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(in, out, s) +} + +func autoConvert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in *v1beta1.BindingProfile, out *BindingProfile, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.OVSHWOffload, &out.OVSHWOffload, s); err != nil { + return err + } + if err := v1.Convert_Pointer_bool_To_bool(&in.TrustedVF, &out.TrustedVF, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile is an autogenerated conversion function. +func Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in *v1beta1.BindingProfile, out *BindingProfile, s conversion.Scope) error { + return autoConvert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in, out, s) +} + +func autoConvert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(in *BlockDeviceStorage, out *v1beta1.BlockDeviceStorage, s conversion.Scope) error { + out.Type = v1beta1.BlockDeviceType(in.Type) + if in.Volume != nil { + in, out := &in.Volume, &out.Volume + *out = new(v1beta1.BlockDeviceVolume) + if err := Convert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(*in, *out, s); err != nil { + return err + } + } else { + out.Volume = nil + } + return nil +} + +// Convert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage is an autogenerated conversion function. +func Convert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(in *BlockDeviceStorage, out *v1beta1.BlockDeviceStorage, s conversion.Scope) error { + return autoConvert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(in, out, s) +} + +func autoConvert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1beta1.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error { + out.Type = BlockDeviceType(in.Type) + if in.Volume != nil { + in, out := &in.Volume, &out.Volume + *out = new(BlockDeviceVolume) + if err := Convert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(*in, *out, s); err != nil { + return err + } + } else { + out.Volume = nil + } + return nil +} + +// Convert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage is an autogenerated conversion function. +func Convert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1beta1.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error { + return autoConvert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in, out, s) +} + +func autoConvert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(in *BlockDeviceVolume, out *v1beta1.BlockDeviceVolume, s conversion.Scope) error { + out.Type = in.Type + if err := conversioncommon.Convert_string_To_Pointer_v1beta1_VolumeAvailabilityZone(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume is an autogenerated conversion function. +func Convert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(in *BlockDeviceVolume, out *v1beta1.BlockDeviceVolume, s conversion.Scope) error { + return autoConvert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(in, out, s) +} + +func autoConvert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1beta1.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error { + out.Type = in.Type + if err := conversioncommon.Convert_Pointer_v1beta1_VolumeAvailabilityZone_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume is an autogenerated conversion function. +func Convert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1beta1.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error { + return autoConvert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in, out, s) +} + +func autoConvert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1beta1.ExternalRouterIPParam, s conversion.Scope) error { + out.FixedIP = in.FixedIP + if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam is an autogenerated conversion function. +func Convert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1beta1.ExternalRouterIPParam, s conversion.Scope) error { + return autoConvert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in, out, s) +} + +func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { + out.FixedIP = in.FixedIP + if err := Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam is an autogenerated conversion function. +func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error { + return autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in, out, s) +} + +func autoConvert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error { + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(v1beta1.SubnetParam) + if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(*in, *out, s); err != nil { + return err + } + } else { + out.Subnet = nil + } + if err := optional.Convert_string_To_optional_String(&in.IPAddress, &out.IPAddress, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_FixedIP_To_v1beta1_FixedIP is an autogenerated conversion function. +func Convert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error { + return autoConvert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in, out, s) +} + +func autoConvert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error { + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(SubnetFilter) + if err := Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Subnet = nil + } + if err := optional.Convert_optional_String_To_string(&in.IPAddress, &out.IPAddress, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_FixedIP_To_v1alpha7_FixedIP is an autogenerated conversion function. +func Convert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error { + return autoConvert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in, out, s) +} + +func autoConvert_v1alpha7_LoadBalancer_To_v1beta1_LoadBalancer(in *LoadBalancer, out *v1beta1.LoadBalancer, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.IP = in.IP + out.InternalIP = in.InternalIP + out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + return nil +} + +// Convert_v1alpha7_LoadBalancer_To_v1beta1_LoadBalancer is an autogenerated conversion function. +func Convert_v1alpha7_LoadBalancer_To_v1beta1_LoadBalancer(in *LoadBalancer, out *v1beta1.LoadBalancer, s conversion.Scope) error { + return autoConvert_v1alpha7_LoadBalancer_To_v1beta1_LoadBalancer(in, out, s) +} + +func autoConvert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.IP = in.IP + out.InternalIP = in.InternalIP + out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs)) + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.LoadBalancerNetwork requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error { + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error { + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus(in *NetworkStatus, out *v1beta1.NetworkStatus, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + return nil +} + +// Convert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus is an autogenerated conversion function. +func Convert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus(in *NetworkStatus, out *v1beta1.NetworkStatus, s conversion.Scope) error { + return autoConvert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus(in, out, s) +} + +func autoConvert_v1beta1_NetworkStatus_To_v1alpha7_NetworkStatus(in *v1beta1.NetworkStatus, out *NetworkStatus, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + return nil +} + +// Convert_v1beta1_NetworkStatus_To_v1alpha7_NetworkStatus is an autogenerated conversion function. +func Convert_v1beta1_NetworkStatus_To_v1alpha7_NetworkStatus(in *v1beta1.NetworkStatus, out *NetworkStatus, s conversion.Scope) error { + return autoConvert_v1beta1_NetworkStatus_To_v1alpha7_NetworkStatus(in, out, s) +} + +func autoConvert_v1alpha7_NetworkStatusWithSubnets_To_v1beta1_NetworkStatusWithSubnets(in *NetworkStatusWithSubnets, out *v1beta1.NetworkStatusWithSubnets, s conversion.Scope) error { + if err := Convert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus(&in.NetworkStatus, &out.NetworkStatus, s); err != nil { + return err + } + out.Subnets = *(*[]v1beta1.Subnet)(unsafe.Pointer(&in.Subnets)) + return nil +} + +// Convert_v1alpha7_NetworkStatusWithSubnets_To_v1beta1_NetworkStatusWithSubnets is an autogenerated conversion function. +func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1beta1_NetworkStatusWithSubnets(in *NetworkStatusWithSubnets, out *v1beta1.NetworkStatusWithSubnets, s conversion.Scope) error { + return autoConvert_v1alpha7_NetworkStatusWithSubnets_To_v1beta1_NetworkStatusWithSubnets(in, out, s) +} + +func autoConvert_v1beta1_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in *v1beta1.NetworkStatusWithSubnets, out *NetworkStatusWithSubnets, s conversion.Scope) error { + if err := Convert_v1beta1_NetworkStatus_To_v1alpha7_NetworkStatus(&in.NetworkStatus, &out.NetworkStatus, s); err != nil { + return err + } + out.Subnets = *(*[]Subnet)(unsafe.Pointer(&in.Subnets)) + return nil +} + +// Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets is an autogenerated conversion function. +func Convert_v1beta1_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in *v1beta1.NetworkStatusWithSubnets, out *NetworkStatusWithSubnets, s conversion.Scope) error { + return autoConvert_v1beta1_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster(in, out, s) +} + +func autoConvert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster is an autogenerated conversion function. +func Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in *OpenStackClusterList, out *v1beta1.OpenStackClusterList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.OpenStackCluster, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in *OpenStackClusterList, out *v1beta1.OpenStackClusterList, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList(in, out, s) +} + +func autoConvert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1beta1.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackCluster, len(*in)) + for i := range *in { + if err := Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1beta1.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error { + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type + // WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type + if in.Router != nil { + in, out := &in.Router, &out.Router + *out = new(v1beta1.RouterParam) + if err := Convert_v1alpha7_RouterFilter_To_v1beta1_RouterParam(*in, *out, s); err != nil { + return err + } + } else { + out.Router = nil + } + // WARNING: in.Network requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.NetworkFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam) + // WARNING: in.Subnet requires manual conversion: does not exist in peer-type + if err := optional.Convert_int_To_optional_Int(&in.NetworkMTU, &out.NetworkMTU, s); err != nil { + return err + } + // WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type + if in.ExternalRouterIPs != nil { + in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs + *out = make([]v1beta1.ExternalRouterIPParam, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.ExternalRouterIPs = nil + } + // WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type + // WARNING: in.APIServerLoadBalancer requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.APIServerLoadBalancer vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.APIServerLoadBalancer) + if err := optional.Convert_bool_To_optional_Bool(&in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.APIServerFloatingIP, &out.APIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.APIServerFixedIP, &out.APIServerFixedIP, s); err != nil { + return err + } + if err := optional.Convert_int_To_optional_Int(&in.APIServerPort, &out.APIServerPort, s); err != nil { + return err + } + // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups) + // WARNING: in.AllowAllInClusterTraffic requires manual conversion: does not exist in peer-type + if err := optional.Convert_bool_To_optional_Bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil { + return err + } + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.ControlPlaneEndpoint requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint vs *sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint) + out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones)) + if err := optional.Convert_bool_To_optional_Bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil { + return err + } + if in.Bastion != nil { + in, out := &in.Bastion, &out.Bastion + *out = new(v1beta1.Bastion) + if err := Convert_v1alpha7_Bastion_To_v1beta1_Bastion(*in, *out, s); err != nil { + return err + } + } else { + out.Bastion = nil + } + // WARNING: in.IdentityRef requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.OpenStackIdentityReference vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference) + return nil +} + +func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { + // WARNING: in.ManagedSubnets requires manual conversion: does not exist in peer-type + if in.Router != nil { + in, out := &in.Router, &out.Router + *out = new(RouterFilter) + if err := Convert_v1beta1_RouterParam_To_v1alpha7_RouterFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Router = nil + } + // WARNING: in.Network requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.NetworkFilter) + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type + if err := optional.Convert_optional_Int_To_int(&in.NetworkMTU, &out.NetworkMTU, s); err != nil { + return err + } + if in.ExternalRouterIPs != nil { + in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs + *out = make([]ExternalRouterIPParam, len(*in)) + for i := range *in { + if err := Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.ExternalRouterIPs = nil + } + // WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type + // WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type + // WARNING: in.APIServerLoadBalancer requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.APIServerLoadBalancer vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.APIServerLoadBalancer) + if err := optional.Convert_optional_Bool_To_bool(&in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.APIServerFloatingIP, &out.APIServerFloatingIP, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.APIServerFixedIP, &out.APIServerFixedIP, s); err != nil { + return err + } + if err := optional.Convert_optional_Int_To_int(&in.APIServerPort, &out.APIServerPort, s); err != nil { + return err + } + // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool) + if err := optional.Convert_optional_Bool_To_bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil { + return err + } + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.ControlPlaneEndpoint requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint vs sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint) + out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones)) + if err := optional.Convert_optional_Bool_To_bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil { + return err + } + if in.Bastion != nil { + in, out := &in.Bastion, &out.Bastion + *out = new(Bastion) + if err := Convert_v1beta1_Bastion_To_v1alpha7_Bastion(*in, *out, s); err != nil { + return err + } + } else { + out.Bastion = nil + } + // WARNING: in.IdentityRef requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.OpenStackIdentityReference) + return nil +} + +func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1beta1.OpenStackClusterStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Network = (*v1beta1.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network)) + out.ExternalNetwork = (*v1beta1.NetworkStatus)(unsafe.Pointer(in.ExternalNetwork)) + out.Router = (*v1beta1.Router)(unsafe.Pointer(in.Router)) + if in.APIServerLoadBalancer != nil { + in, out := &in.APIServerLoadBalancer, &out.APIServerLoadBalancer + *out = new(v1beta1.LoadBalancer) + if err := Convert_v1alpha7_LoadBalancer_To_v1beta1_LoadBalancer(*in, *out, s); err != nil { + return err + } + } else { + out.APIServerLoadBalancer = nil + } + out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) + if in.ControlPlaneSecurityGroup != nil { + in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.ControlPlaneSecurityGroup = nil + } + if in.WorkerSecurityGroup != nil { + in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.WorkerSecurityGroup = nil + } + if in.BastionSecurityGroup != nil { + in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup + *out = new(v1beta1.SecurityGroupStatus) + if err := Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil { + return err + } + } else { + out.BastionSecurityGroup = nil + } + if in.Bastion != nil { + in, out := &in.Bastion, &out.Bastion + *out = new(v1beta1.BastionStatus) + if err := Convert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus(*in, *out, s); err != nil { + return err + } + } else { + out.Bastion = nil + } + out.FailureReason = (*errors.ClusterStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + return nil +} + +// Convert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1beta1.OpenStackClusterStatus, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in, out, s) +} + +func autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *v1beta1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Network = (*NetworkStatusWithSubnets)(unsafe.Pointer(in.Network)) + out.ExternalNetwork = (*NetworkStatus)(unsafe.Pointer(in.ExternalNetwork)) + out.Router = (*Router)(unsafe.Pointer(in.Router)) + if in.APIServerLoadBalancer != nil { + in, out := &in.APIServerLoadBalancer, &out.APIServerLoadBalancer + *out = new(LoadBalancer) + if err := Convert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(*in, *out, s); err != nil { + return err + } + } else { + out.APIServerLoadBalancer = nil + } + out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains)) + if in.ControlPlaneSecurityGroup != nil { + in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.ControlPlaneSecurityGroup = nil + } + if in.WorkerSecurityGroup != nil { + in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.WorkerSecurityGroup = nil + } + if in.BastionSecurityGroup != nil { + in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup + *out = new(SecurityGroup) + if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil { + return err + } + } else { + out.BastionSecurityGroup = nil + } + if in.Bastion != nil { + in, out := &in.Bastion, &out.Bastion + *out = new(BastionStatus) + if err := Convert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(*in, *out, s); err != nil { + return err + } + } else { + out.Bastion = nil + } + out.FailureReason = (*errors.ClusterStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + return nil +} + +func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1beta1.OpenStackClusterTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1beta1.OpenStackClusterTemplate, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(in, out, s) +} + +func autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1beta1.OpenStackClusterTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.OpenStackClusterTemplate, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha7_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1beta1.OpenStackClusterTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1beta1_OpenStackClusterTemplateList(in, out, s) +} + +func autoConvert_v1beta1_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1beta1.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackClusterTemplate, len(*in)) + for i := range *in { + if err := Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1beta1.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1beta1.OpenStackClusterTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1beta1.OpenStackClusterTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(in, out, s) +} + +func autoConvert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *v1beta1.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *v1beta1.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1beta1.OpenStackClusterTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1beta1_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1beta1.OpenStackClusterTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(in, out, s) +} + +func autoConvert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *v1beta1.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec is an autogenerated conversion function. +func Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *v1beta1.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1beta1.OpenStackIdentityReference, s conversion.Scope) error { + // WARNING: in.Kind requires manual conversion: does not exist in peer-type + out.Name = in.Name + return nil +} + +func autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error { + out.Name = in.Name + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.OpenStackMachine, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in, out, s) +} + +func autoConvert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1beta1.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackMachine, len(*in)) + for i := range *in { + if err := Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1beta1.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1beta1.OpenStackMachineSpec, s conversion.Scope) error { + out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) + // WARNING: in.InstanceID requires manual conversion: does not exist in peer-type + // WARNING: in.CloudName requires manual conversion: does not exist in peer-type + out.Flavor = in.Flavor + // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam) + // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type + out.SSHKeyName = in.SSHKeyName + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]v1beta1.PortOpts, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Ports = nil + } + // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]v1beta1.SecurityGroupParam, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.SecurityGroups = nil + } + out.Trunk = in.Trunk + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.ServerMetadata requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata) + out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(v1beta1.RootVolume) + if err := Convert_v1alpha7_RootVolume_To_v1beta1_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } + if in.AdditionalBlockDevices != nil { + in, out := &in.AdditionalBlockDevices, &out.AdditionalBlockDevices + *out = make([]v1beta1.AdditionalBlockDevice, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.AdditionalBlockDevices = nil + } + // WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(v1beta1.OpenStackIdentityReference) + if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil { + return err + } + } else { + out.IdentityRef = nil + } + return nil +} + +func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *v1beta1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { + out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) + out.Flavor = in.Flavor + // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam vs string) + out.SSHKeyName = in.SSHKeyName + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]PortOpts, len(*in)) + for i := range *in { + if err := Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Ports = nil + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]SecurityGroupFilter, len(*in)) + for i := range *in { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.SecurityGroups = nil + } + out.Trunk = in.Trunk + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.ServerMetadata requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata vs map[string]string) + out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + if err := Convert_v1beta1_RootVolume_To_v1alpha7_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } + if in.AdditionalBlockDevices != nil { + in, out := &in.AdditionalBlockDevices, &out.AdditionalBlockDevices + *out = make([]AdditionalBlockDevice, len(*in)) + for i := range *in { + if err := Convert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.AdditionalBlockDevices = nil + } + // WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type + if in.IdentityRef != nil { + in, out := &in.IdentityRef, &out.IdentityRef + *out = new(OpenStackIdentityReference) + if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil { + return err + } + } else { + out.IdentityRef = nil + } + // WARNING: in.FloatingIPPoolRef requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1beta1.OpenStackMachineStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.InstanceState = (*v1beta1.InstanceState)(unsafe.Pointer(in.InstanceState)) + out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + out.Conditions = *(*apiv1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1beta1.OpenStackMachineStatus, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(in, out, s) +} + +func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1beta1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error { + out.Ready = in.Ready + // WARNING: in.InstanceID requires manual conversion: does not exist in peer-type + out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses)) + out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState)) + // WARNING: in.Resolved requires manual conversion: does not exist in peer-type + // WARNING: in.Resources requires manual conversion: does not exist in peer-type + out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) + out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + out.Conditions = *(*apiv1beta1.Conditions)(unsafe.Pointer(&in.Conditions)) + return nil +} + +func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1beta1.OpenStackMachineTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1beta1.OpenStackMachineTemplate, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(in, out, s) +} + +func autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1beta1.OpenStackMachineTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.OpenStackMachineTemplate, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1beta1.OpenStackMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(in, out, s) +} + +func autoConvert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1beta1.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackMachineTemplate, len(*in)) + for i := range *in { + if err := Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1beta1.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1beta1.OpenStackMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1beta1.OpenStackMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(in, out, s) +} + +func autoConvert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *v1beta1.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *v1beta1.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in, out, s) +} + +func autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1beta1.OpenStackMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1beta1_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1beta1.OpenStackMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(in, out, s) +} + +func autoConvert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *v1beta1.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { + if err := Convert_v1beta1_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec is an autogenerated conversion function. +func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *v1beta1.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in, out, s) +} + +func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error { + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(v1beta1.NetworkParam) + if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkParam(*in, *out, s); err != nil { + return err + } + } else { + out.Network = nil + } + if err := optional.Convert_string_To_optional_String(&in.NameSuffix, &out.NameSuffix, s); err != nil { + return err + } + if err := optional.Convert_string_To_optional_String(&in.Description, &out.Description, s); err != nil { + return err + } + // WARNING: in.AdminStateUp requires manual conversion: does not exist in peer-type + // WARNING: in.MACAddress requires manual conversion: does not exist in peer-type + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]v1beta1.FixedIP, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_FixedIP_To_v1beta1_FixedIP(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.FixedIPs = nil + } + // WARNING: in.SecurityGroupFilters requires manual conversion: does not exist in peer-type + // WARNING: in.AllowedAddressPairs requires manual conversion: does not exist in peer-type + out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) + // WARNING: in.HostID requires manual conversion: does not exist in peer-type + // WARNING: in.VNICType requires manual conversion: does not exist in peer-type + // WARNING: in.Profile requires manual conversion: does not exist in peer-type + // WARNING: in.DisablePortSecurity requires manual conversion: does not exist in peer-type + // WARNING: in.PropagateUplinkStatus requires manual conversion: does not exist in peer-type + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + // WARNING: in.ValueSpecs requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error { + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkFilter) + if err := Convert_v1beta1_NetworkParam_To_v1alpha7_NetworkFilter(*in, *out, s); err != nil { + return err + } + } else { + out.Network = nil + } + if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil { + return err + } + if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil { + return err + } + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]FixedIP, len(*in)) + for i := range *in { + if err := Convert_v1beta1_FixedIP_To_v1alpha7_FixedIP(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.FixedIPs = nil + } + // WARNING: in.SecurityGroups requires manual conversion: does not exist in peer-type + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + out.Trunk = (*bool)(unsafe.Pointer(in.Trunk)) + // WARNING: in.ResolvedPortSpecFields requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error { + // WARNING: in.Size requires manual conversion: does not exist in peer-type + // WARNING: in.VolumeType requires manual conversion: does not exist in peer-type + // WARNING: in.AvailabilityZone requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error { + // WARNING: in.SizeGiB requires manual conversion: does not exist in peer-type + // WARNING: in.BlockDeviceVolume requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + out.IPs = *(*[]string)(unsafe.Pointer(&in.IPs)) + return nil +} + +// Convert_v1alpha7_Router_To_v1beta1_Router is an autogenerated conversion function. +func Convert_v1alpha7_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error { + return autoConvert_v1alpha7_Router_To_v1beta1_Router(in, out, s) +} + +func autoConvert_v1beta1_Router_To_v1alpha7_Router(in *v1beta1.Router, out *Router, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + out.IPs = *(*[]string)(unsafe.Pointer(&in.IPs)) + return nil +} + +// Convert_v1beta1_Router_To_v1alpha7_Router is an autogenerated conversion function. +func Convert_v1beta1_Router_To_v1alpha7_Router(in *v1beta1.Router, out *Router, s conversion.Scope) error { + return autoConvert_v1beta1_Router_To_v1alpha7_Router(in, out, s) +} + +func autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *v1beta1.RouterFilter, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.RouterFilter, out *RouterFilter, s conversion.Scope) error { + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.CIDR = in.CIDR + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + return nil +} + +// Convert_v1alpha7_Subnet_To_v1beta1_Subnet is an autogenerated conversion function. +func Convert_v1alpha7_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { + return autoConvert_v1alpha7_Subnet_To_v1beta1_Subnet(in, out, s) +} + +func autoConvert_v1beta1_Subnet_To_v1alpha7_Subnet(in *v1beta1.Subnet, out *Subnet, s conversion.Scope) error { + out.Name = in.Name + out.ID = in.ID + out.CIDR = in.CIDR + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + return nil +} + +// Convert_v1beta1_Subnet_To_v1alpha7_Subnet is an autogenerated conversion function. +func Convert_v1beta1_Subnet_To_v1alpha7_Subnet(in *v1beta1.Subnet, out *Subnet, s conversion.Scope) error { + return autoConvert_v1beta1_Subnet_To_v1alpha7_Subnet(in, out, s) +} + +func autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error { + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + out.IPVersion = in.IPVersion + out.GatewayIP = in.GatewayIP + out.CIDR = in.CIDR + out.IPv6AddressMode = in.IPv6AddressMode + out.IPv6RAMode = in.IPv6RAMode + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Tags requires manual conversion: does not exist in peer-type + // WARNING: in.TagsAny requires manual conversion: does not exist in peer-type + // WARNING: in.NotTags requires manual conversion: does not exist in peer-type + // WARNING: in.NotTagsAny requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error { + out.Name = in.Name + out.Description = in.Description + out.ProjectID = in.ProjectID + out.IPVersion = in.IPVersion + out.GatewayIP = in.GatewayIP + out.CIDR = in.CIDR + out.IPv6AddressMode = in.IPv6AddressMode + out.IPv6RAMode = in.IPv6RAMode + // WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha7_ValueSpec_To_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error { + out.Name = in.Name + out.Key = in.Key + out.Value = in.Value + return nil +} + +// Convert_v1alpha7_ValueSpec_To_v1beta1_ValueSpec is an autogenerated conversion function. +func Convert_v1alpha7_ValueSpec_To_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error { + return autoConvert_v1alpha7_ValueSpec_To_v1beta1_ValueSpec(in, out, s) +} + +func autoConvert_v1beta1_ValueSpec_To_v1alpha7_ValueSpec(in *v1beta1.ValueSpec, out *ValueSpec, s conversion.Scope) error { + out.Name = in.Name + out.Key = in.Key + out.Value = in.Value + return nil +} + +// Convert_v1beta1_ValueSpec_To_v1alpha7_ValueSpec is an autogenerated conversion function. +func Convert_v1beta1_ValueSpec_To_v1alpha7_ValueSpec(in *v1beta1.ValueSpec, out *ValueSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ValueSpec_To_v1alpha7_ValueSpec(in, out, s) +} diff --git a/api/v1alpha7/zz_generated.deepcopy.go b/api/v1alpha7/zz_generated.deepcopy.go index 1d81a83410..daa1524d33 100644 --- a/api/v1alpha7/zz_generated.deepcopy.go +++ b/api/v1alpha7/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ package v1alpha7 import ( "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/errors" ) diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/conditions_consts.go b/api/v1beta1/conditions_consts.go similarity index 78% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/conditions_consts.go rename to api/v1beta1/conditions_consts.go index b54eade0b0..cbddf42077 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/conditions_consts.go +++ b/api/v1beta1/conditions_consts.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 +package v1beta1 import clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -53,3 +53,14 @@ const ( // FloatingIPErrorReason used when the floating ip could not be created or attached. FloatingIPErrorReason = "FloatingIPError" ) + +const ( + // FloatingAddressFromPoolReadyCondition reports on the current status of the Floating IPs from ipam pool. + FloatingAddressFromPoolReadyCondition clusterv1.ConditionType = "FloatingAddressFromPoolReady" + // WaitingForIpamProviderReason used when machine is waiting for ipam provider to be ready before proceeding. + FloatingAddressFromPoolWaitingForIpamProviderReason = "WaitingForIPAMProvider" + // FloatingAddressFromPoolErrorReason is used when there is an error attaching an IP from the pool to an machine. + FloatingAddressFromPoolErrorReason = "FloatingIPError" + // UnableToFindFloatingIPNetworkReason is used when the floating ip network is not found. + UnableToFindFloatingIPNetworkReason = "UnableToFindFloatingIPNetwork" +) diff --git a/api/v1beta1/conversion.go b/api/v1beta1/conversion.go new file mode 100644 index 0000000000..d442dc0f1d --- /dev/null +++ b/api/v1beta1/conversion.go @@ -0,0 +1,117 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "strings" + + "k8s.io/utils/ptr" +) + +// Hub marks OpenStackCluster as a conversion hub. +func (*OpenStackCluster) Hub() {} + +// Hub marks OpenStackClusterList as a conversion hub. +func (*OpenStackClusterList) Hub() {} + +// Hub marks OpenStackClusterTemplate as a conversion hub. +func (*OpenStackClusterTemplate) Hub() {} + +// Hub marks OpenStackClusterTemplateList as a conversion hub. +func (*OpenStackClusterTemplateList) Hub() {} + +// Hub marks OpenStackMachine as a conversion hub. +func (*OpenStackMachine) Hub() {} + +// Hub marks OpenStackMachineList as a conversion hub. +func (*OpenStackMachineList) Hub() {} + +// Hub marks OpenStackMachineTemplate as a conversion hub. +func (*OpenStackMachineTemplate) Hub() {} + +// Hub marks OpenStackMachineTemplateList as a conversion hub. +func (*OpenStackMachineTemplateList) Hub() {} + +// LegacyCalicoSecurityGroupRules returns a list of security group rules for calico +// that need to be applied to the control plane and worker security groups when +// managed security groups are enabled and upgrading to v1beta1. +func LegacyCalicoSecurityGroupRules() []SecurityGroupRuleSpec { + return []SecurityGroupRuleSpec{ + { + Name: "BGP (calico)", + Description: ptr.To("Created by cluster-api-provider-openstack API conversion - BGP (calico)"), + Direction: "ingress", + EtherType: ptr.To("IPv4"), + PortRangeMin: ptr.To(179), + PortRangeMax: ptr.To(179), + Protocol: ptr.To("tcp"), + RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"}, + }, + { + Name: "IP-in-IP (calico)", + Description: ptr.To("Created by cluster-api-provider-openstack API conversion - IP-in-IP (calico)"), + Direction: "ingress", + EtherType: ptr.To("IPv4"), + Protocol: ptr.To("4"), + RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"}, + }, + } +} + +// splitTags splits a comma separated list of tags into a slice of tags. +// If the input is an empty string, it returns nil representing no list rather +// than an empty list. +func splitTags(tags string) []NeutronTag { + if tags == "" { + return nil + } + + var ret []NeutronTag + for _, tag := range strings.Split(tags, ",") { + if tag != "" { + ret = append(ret, NeutronTag(tag)) + } + } + + return ret +} + +// JoinTags joins a slice of tags into a comma separated list of tags. +func JoinTags(tags []NeutronTag) string { + var b strings.Builder + for i := range tags { + if i > 0 { + b.WriteString(",") + } + b.WriteString(string(tags[i])) + } + return b.String() +} + +func ConvertAllTagsTo(tags, tagsAny, notTags, notTagsAny string, neutronTags *FilterByNeutronTags) { + neutronTags.Tags = splitTags(tags) + neutronTags.TagsAny = splitTags(tagsAny) + neutronTags.NotTags = splitTags(notTags) + neutronTags.NotTagsAny = splitTags(notTagsAny) +} + +func ConvertAllTagsFrom(neutronTags *FilterByNeutronTags, tags, tagsAny, notTags, notTagsAny *string) { + *tags = JoinTags(neutronTags.Tags) + *tagsAny = JoinTags(neutronTags.TagsAny) + *notTags = JoinTags(neutronTags.NotTags) + *notTagsAny = JoinTags(neutronTags.NotTagsAny) +} diff --git a/api/v1beta1/doc.go b/api/v1beta1/doc.go new file mode 100644 index 0000000000..4bd2e99487 --- /dev/null +++ b/api/v1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group. +// +kubebuilder:object:generate=true +// +groupName=infrastructure.cluster.x-k8s.io +package v1beta1 diff --git a/api/v1beta1/groupversion_info.go b/api/v1beta1/groupversion_info.go new file mode 100644 index 0000000000..de2087f709 --- /dev/null +++ b/api/v1beta1/groupversion_info.go @@ -0,0 +1,45 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group +// +kubebuilder:object:generate=true +// +groupName=infrastructure.cluster.x-k8s.io +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1beta1"} + + // schemeBuilder is used to add go types to the GroupVersionKind scheme. + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = schemeBuilder.AddToScheme + + objectTypes = []runtime.Object{} +) + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(GroupVersion, objectTypes...) + metav1.AddToGroupVersion(scheme, GroupVersion) + return nil +} diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/identity_types.go b/api/v1beta1/identity_types.go similarity index 60% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/identity_types.go rename to api/v1beta1/identity_types.go index 15cd58562b..d54ed749e4 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/identity_types.go +++ b/api/v1beta1/identity_types.go @@ -14,20 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 - -const defaultIdentityRefKind = "Secret" +package v1beta1 // OpenStackIdentityReference is a reference to an infrastructure // provider identity to be used to provision cluster resources. type OpenStackIdentityReference struct { - // Kind of the identity. Must be supported by the infrastructure - // provider and may be either cluster or namespace-scoped. - // +kubebuilder:validation:MinLength=1 - Kind string `json:"kind"` - - // Name of the infrastructure identity to be used. - // Must be either a cluster-scoped resource, or namespaced-scoped - // resource the same namespace as the resource(s) being provisioned. + // Name is the name of a secret in the same namespace as the resource being provisioned. + // The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + // The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + // +kubebuilder:validation:Required Name string `json:"name"` + + // CloudName specifies the name of the entry in the clouds.yaml file to use. + // +kubebuilder:validation:Required + CloudName string `json:"cloudName"` } diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go similarity index 57% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackcluster_types.go rename to api/v1beta1/openstackcluster_types.go index b4826685b0..d6745e5ccd 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackcluster_types.go +++ b/api/v1beta1/openstackcluster_types.go @@ -14,12 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 +package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" capierrors "sigs.k8s.io/cluster-api/errors" + + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" ) const ( @@ -30,50 +32,72 @@ const ( // OpenStackClusterSpec defines the desired state of OpenStackCluster. type OpenStackClusterSpec struct { - // The name of the cloud to use from the clouds secret + // ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network, + // subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4 + // subnet is supported. If you leave this empty, no network will be created. + // +kubebuilder:validation:MaxItems=1 + // +listType=atomic // +optional - CloudName string `json:"cloudName"` - - // NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a - // network, a subnet with NodeCIDR, and a router connected to this subnet. - // If you leave this empty, no network will be created. - NodeCIDR string `json:"nodeCidr,omitempty"` + ManagedSubnets []SubnetSpec `json:"managedSubnets,omitempty"` - // If NodeCIDR is set this option can be used to detect an existing router. - // If specified, no new router will be created. + // Router specifies an existing router to be used if ManagedSubnets are + // specified. If specified, no new router will be created. // +optional - Router *RouterFilter `json:"router,omitempty"` - - // If NodeCIDR cannot be set this can be used to detect an existing network. - Network NetworkFilter `json:"network,omitempty"` + Router *RouterParam `json:"router,omitempty"` - // If NodeCIDR cannot be set this can be used to detect an existing subnet. - Subnet SubnetFilter `json:"subnet,omitempty"` + // Network specifies an existing network to use if no ManagedSubnets + // are specified. + // +optional + Network *NetworkParam `json:"network,omitempty"` + + // Subnets specifies existing subnets to use if not ManagedSubnets are + // specified. All subnets must be in the network specified by Network. + // There can be zero, one, or two subnets. If no subnets are specified, + // all subnets in Network will be used. If 2 subnets are specified, one + // must be IPv4 and the other IPv6. + // +kubebuilder:validation:MaxItems=2 + // +listType=atomic + // +optional + Subnets []SubnetParam `json:"subnets,omitempty"` // NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. // This value will be used only if the Cluster actuator creates the network. - // If leaved empty, the network will have the default MTU defined in Openstack network service. + // If left empty, the network will have the default MTU defined in Openstack network service. // To use this field, the Openstack installation requires the net-mtu neutron API extension. // +optional - NetworkMTU int `json:"networkMtu,omitempty"` + NetworkMTU optional.Int `json:"networkMTU,omitempty"` - // DNSNameservers is the list of nameservers for OpenStack Subnet being created. - // Set this value when you need create a new network/subnet while the access - // through DNS is required. - // +listType=set - DNSNameservers []string `json:"dnsNameservers,omitempty"` // ExternalRouterIPs is an array of externalIPs on the respective subnets. // This is necessary if the router needs a fixed ip in a specific subnet. + // +listType=atomic + // +optional ExternalRouterIPs []ExternalRouterIPParam `json:"externalRouterIPs,omitempty"` - // ExternalNetworkID is the ID of an external OpenStack Network. This is necessary - // to get public internet to the VMs. + + // ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. + // This option is ignored if DisableExternalNetwork is set to true. + // + // If ExternalNetwork is defined it must refer to exactly one external network. + // + // If ExternalNetwork is not defined or is empty the controller will use any + // existing external network as long as there is only one. It is an + // error if ExternalNetwork is not defined and there are multiple + // external networks unless DisableExternalNetwork is also set. + // + // If ExternalNetwork is not defined and there are no external networks + // the controller will proceed as though DisableExternalNetwork was set. + // +optional + ExternalNetwork *NetworkParam `json:"externalNetwork,omitempty"` + + // DisableExternalNetwork specifies whether or not to attempt to connect the cluster + // to an external network. This allows for the creation of clusters when connecting + // to an external network is not possible or desirable, e.g. if using a provider network. // +optional - ExternalNetworkID string `json:"externalNetworkId,omitempty"` + DisableExternalNetwork optional.Bool `json:"disableExternalNetwork,omitempty"` // APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. - // It must be activated by setting `enabled: true`. + // If not specified, no load balancer will be created for the API server. // +optional - APIServerLoadBalancer APIServerLoadBalancer `json:"apiServerLoadBalancer,omitempty"` + APIServerLoadBalancer *APIServerLoadBalancer `json:"apiServerLoadBalancer,omitempty"` // DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating // IP to the API server. This allows for the creation of clusters when attaching a floating @@ -88,13 +112,14 @@ type OpenStackClusterSpec struct { // configuration to manage the VIP on the control plane machines, which falls outside of // the scope of this controller. // +optional - DisableAPIServerFloatingIP bool `json:"disableAPIServerFloatingIP"` + DisableAPIServerFloatingIP optional.Bool `json:"disableAPIServerFloatingIP,omitempty"` // APIServerFloatingIP is the floatingIP which will be associated with the API server. // The floatingIP will be created if it does not already exist. // If not specified, a new floatingIP is allocated. // This field is not used if DisableAPIServerFloatingIP is set to true. - APIServerFloatingIP string `json:"apiServerFloatingIP,omitempty"` + // +optional + APIServerFloatingIP optional.String `json:"apiServerFloatingIP,omitempty"` // APIServerFixedIP is the fixed IP which will be associated with the API server. // In the case where the API server has a floating IP but not a managed load balancer, @@ -104,90 +129,114 @@ type OpenStackClusterSpec struct { // If a managed load balancer is not used AND the API server floating IP is disabled, // this field MUST be specified and should correspond to a pre-allocated port that // holds the fixed IP to be used as a VIP. - APIServerFixedIP string `json:"apiServerFixedIP,omitempty"` + // +optional + APIServerFixedIP optional.String `json:"apiServerFixedIP,omitempty"` // APIServerPort is the port on which the listener on the APIServer // will be created - APIServerPort int `json:"apiServerPort,omitempty"` + // +optional + APIServerPort optional.Int `json:"apiServerPort,omitempty"` // ManagedSecurityGroups determines whether OpenStack security groups for the cluster // will be managed by the OpenStack provider or whether pre-existing security groups will // be specified as part of the configuration. - // By default, the managed security groups have rules that allow the Kubelet, etcd, the - // Kubernetes API server and the Calico CNI plugin to function correctly. - // +optional - ManagedSecurityGroups bool `json:"managedSecurityGroups"` - - // AllowAllInClusterTraffic is only used when managed security groups are in use. - // If set to true, the rules for the managed security groups are configured so that all - // ingress and egress between cluster nodes is permitted, allowing CNIs other than - // Calico to be used. + // By default, the managed security groups have rules that allow the Kubelet, etcd, and the + // Kubernetes API server to function correctly. + // It's possible to add additional rules to the managed security groups. + // When defined to an empty struct, the managed security groups will be created with the default rules. // +optional - AllowAllInClusterTraffic bool `json:"allowAllInClusterTraffic"` + ManagedSecurityGroups *ManagedSecurityGroups `json:"managedSecurityGroups,omitempty"` // DisablePortSecurity disables the port security of the network created for the // Kubernetes cluster, which also disables SecurityGroups - DisablePortSecurity bool `json:"disablePortSecurity,omitempty"` + // +optional + DisablePortSecurity optional.Bool `json:"disablePortSecurity,omitempty"` - // Tags for all resources in cluster + // Tags to set on all resources in cluster which support tags // +listType=set + // +optional Tags []string `json:"tags,omitempty"` // ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. + // It is normally populated automatically by the OpenStackCluster + // controller during cluster provisioning. If it is set on creation the + // control plane endpoint will use the values set here in preference to + // values set elsewhere. + // ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set. // +optional - ControlPlaneEndpoint clusterv1.APIEndpoint `json:"controlPlaneEndpoint"` + ControlPlaneEndpoint *clusterv1.APIEndpoint `json:"controlPlaneEndpoint,omitempty"` - // ControlPlaneAvailabilityZones is the az to deploy control plane to + // ControlPlaneAvailabilityZones is the set of availability zones which + // control plane machines may be deployed to. // +listType=set + // +optional ControlPlaneAvailabilityZones []string `json:"controlPlaneAvailabilityZones,omitempty"` - // Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler - // to make a decision on which az to use based on other scheduling constraints - ControlPlaneOmitAvailabilityZone bool `json:"controlPlaneOmitAvailabilityZone,omitempty"` + // ControlPlaneOmitAvailabilityZone causes availability zone to be + // omitted when creating control plane nodes, allowing the Nova + // scheduler to make a decision on which availability zone to use based + // on other scheduling constraints + // +optional + ControlPlaneOmitAvailabilityZone optional.Bool `json:"controlPlaneOmitAvailabilityZone,omitempty"` // Bastion is the OpenStack instance to login the nodes // // As a rolling update is not ideal during a bastion host session, we - // prevent changes to a running bastion configuration. Set `enabled: false` to - // make changes. + // prevent changes to a running bastion configuration. To make changes, it's required + // to first set `enabled: false` which will remove the bastion and then changes can be made. //+optional Bastion *Bastion `json:"bastion,omitempty"` - // IdentityRef is a reference to a identity to be used when reconciling this cluster - // +optional - IdentityRef *OpenStackIdentityReference `json:"identityRef,omitempty"` + // IdentityRef is a reference to a secret holding OpenStack credentials + // to be used when reconciling this cluster. It is also to reconcile + // machines unless overridden in the machine spec. + // +kubebuilder:validation:Required + IdentityRef OpenStackIdentityReference `json:"identityRef"` } // OpenStackClusterStatus defines the observed state of OpenStackCluster. type OpenStackClusterStatus struct { + // Ready is true when the cluster infrastructure is ready. + // +kubebuilder:default=false Ready bool `json:"ready"` // Network contains information about the created OpenStack Network. + // +optional Network *NetworkStatusWithSubnets `json:"network,omitempty"` - // externalNetwork contains information about the external network used for default ingress and egress traffic. + // ExternalNetwork contains information about the external network used for default ingress and egress traffic. + // +optional ExternalNetwork *NetworkStatus `json:"externalNetwork,omitempty"` // Router describes the default cluster router + // +optional Router *Router `json:"router,omitempty"` // APIServerLoadBalancer describes the api server load balancer if one exists + // +optional APIServerLoadBalancer *LoadBalancer `json:"apiServerLoadBalancer,omitempty"` // FailureDomains represent OpenStack availability zones FailureDomains clusterv1.FailureDomains `json:"failureDomains,omitempty"` - // ControlPlaneSecurityGroups contains all the information about the OpenStack - // Security Group that needs to be applied to control plane nodes. - // TODO: Maybe instead of two properties, we add a property to the group? - ControlPlaneSecurityGroup *SecurityGroup `json:"controlPlaneSecurityGroup,omitempty"` + // ControlPlaneSecurityGroup contains the information about the + // OpenStack Security Group that needs to be applied to control plane + // nodes. + // +optional + ControlPlaneSecurityGroup *SecurityGroupStatus `json:"controlPlaneSecurityGroup,omitempty"` - // WorkerSecurityGroup contains all the information about the OpenStack Security - // Group that needs to be applied to worker nodes. - WorkerSecurityGroup *SecurityGroup `json:"workerSecurityGroup,omitempty"` + // WorkerSecurityGroup contains the information about the OpenStack + // Security Group that needs to be applied to worker nodes. + // +optional + WorkerSecurityGroup *SecurityGroupStatus `json:"workerSecurityGroup,omitempty"` - BastionSecurityGroup *SecurityGroup `json:"bastionSecurityGroup,omitempty"` + // BastionSecurityGroup contains the information about the OpenStack + // Security Group that needs to be applied to worker nodes. + // +optional + BastionSecurityGroup *SecurityGroupStatus `json:"bastionSecurityGroup,omitempty"` + // Bastion contains the information about the deployed bastion host + // +optional Bastion *BastionStatus `json:"bastion,omitempty"` // FailureReason will be set in the event that there is a terminal problem @@ -229,6 +278,8 @@ type OpenStackClusterStatus struct { FailureMessage *string `json:"failureMessage,omitempty"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true // +kubebuilder:resource:path=openstackclusters,scope=Namespaced,categories=cluster-api,shortName=osc // +kubebuilder:storageversion @@ -258,6 +309,22 @@ type OpenStackClusterList struct { Items []OpenStackCluster `json:"items"` } +// ManagedSecurityGroups defines the desired state of security groups and rules for the cluster. +type ManagedSecurityGroups struct { + // allNodesSecurityGroupRules defines the rules that should be applied to all nodes. + // +patchMergeKey=name + // +patchStrategy=merge + // +listType=map + // +listMapKey=name + // +optional + AllNodesSecurityGroupRules []SecurityGroupRuleSpec `json:"allNodesSecurityGroupRules,omitempty" patchStrategy:"merge" patchMergeKey:"name"` + + // AllowAllInClusterTraffic allows all ingress and egress traffic between cluster nodes when set to true. + // +kubebuilder:default=false + // +kubebuilder:validation:Required + AllowAllInClusterTraffic bool `json:"allowAllInClusterTraffic"` +} + func init() { - SchemeBuilder.Register(&OpenStackCluster{}, &OpenStackClusterList{}) + objectTypes = append(objectTypes, &OpenStackCluster{}, &OpenStackClusterList{}) } diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackclustertemplate_types.go b/api/v1beta1/openstackclustertemplate_types.go similarity index 84% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackclustertemplate_types.go rename to api/v1beta1/openstackclustertemplate_types.go index c255284a77..8516831b60 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackclustertemplate_types.go +++ b/api/v1beta1/openstackclustertemplate_types.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 +package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,9 +30,11 @@ type OpenStackClusterTemplateSpec struct { Template OpenStackClusterTemplateResource `json:"template"` } -//+kubebuilder:object:root=true +// +genclient +// +genclient:Namespaced +// +kubebuilder:object:root=true // +kubebuilder:storageversion -//+kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct +// +kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct // OpenStackClusterTemplate is the Schema for the openstackclustertemplates API. type OpenStackClusterTemplate struct { @@ -52,5 +54,5 @@ type OpenStackClusterTemplateList struct { } func init() { - SchemeBuilder.Register(&OpenStackClusterTemplate{}, &OpenStackClusterTemplateList{}) + objectTypes = append(objectTypes, &OpenStackClusterTemplate{}, &OpenStackClusterTemplateList{}) } diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go similarity index 74% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackmachine_types.go rename to api/v1beta1/openstackmachine_types.go index f5f4f698aa..4a6e798426 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackmachine_types.go +++ b/api/v1beta1/openstackmachine_types.go @@ -14,20 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 +package v1beta1 import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/errors" + + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" ) const ( // MachineFinalizer allows ReconcileOpenStackMachine to clean up OpenStack resources associated with OpenStackMachine before // removing it from the apiserver. - MachineFinalizer = "openstackmachine.infrastructure.cluster.x-k8s.io" + MachineFinalizer = "openstackmachine.infrastructure.cluster.x-k8s.io" + IPClaimMachineFinalizer = "openstackmachine.infrastructure.cluster.x-k8s.io/ip-claim" ) // OpenStackMachineSpec defines the desired state of OpenStackMachine. @@ -35,23 +38,13 @@ type OpenStackMachineSpec struct { // ProviderID is the unique identifier as specified by the cloud provider. ProviderID *string `json:"providerID,omitempty"` - // InstanceID is the OpenStack instance ID for this machine. - InstanceID *string `json:"instanceID,omitempty"` - - // The name of the cloud to use from the clouds secret - // +optional - CloudName string `json:"cloudName"` - // The flavor reference for the flavor for your server instance. Flavor string `json:"flavor"` - // The name of the image to use for your server instance. - // If the RootVolume is specified, this will be ignored and use rootVolume directly. - Image string `json:"image,omitempty"` - - // The uuid of the image to use for your server instance. - // if it's empty, Image name will be used - ImageUUID string `json:"imageUUID,omitempty"` + // The image to use for your server instance. + // If the rootVolume is specified, this will be used when creating the root volume. + // +required + Image ImageParam `json:"image"` // The ssh key to inject in the instance SSHKeyName string `json:"sshKeyName,omitempty"` @@ -60,23 +53,23 @@ type OpenStackMachineSpec struct { // If not specified a default port will be added for the default cluster network. Ports []PortOpts `json:"ports,omitempty"` - // The floatingIP which will be associated to the machine, only used for master. - // The floatingIP should have been created and haven't been associated. - FloatingIP string `json:"floatingIP,omitempty"` - // The names of the security groups to assign to the instance - SecurityGroups []SecurityGroupFilter `json:"securityGroups,omitempty"` + SecurityGroups []SecurityGroupParam `json:"securityGroups,omitempty"` // Whether the server instance is created on a trunk port or not. Trunk bool `json:"trunk,omitempty"` - // Machine tags + // Tags which will be added to the machine and all dependent resources + // which support them. These are in addition to Tags defined on the + // cluster. // Requires Nova api 2.52 minimum! // +listType=set Tags []string `json:"tags,omitempty"` // Metadata mapping. Allows you to create a map of key value pairs to add to the server instance. - ServerMetadata map[string]string `json:"serverMetadata,omitempty"` + // +listType=map + // +listMapKey=key + ServerMetadata []ServerMetadata `json:"serverMetadata,omitempty"` // Config Drive support ConfigDrive *bool `json:"configDrive,omitempty"` @@ -90,12 +83,33 @@ type OpenStackMachineSpec struct { // +optional AdditionalBlockDevices []AdditionalBlockDevice `json:"additionalBlockDevices,omitempty"` - // The server group to assign the machine to - ServerGroupID string `json:"serverGroupID,omitempty"` + // The server group to assign the machine to. + // +optional + ServerGroup *ServerGroupParam `json:"serverGroup,omitempty"` - // IdentityRef is a reference to a identity to be used when reconciling this cluster + // IdentityRef is a reference to a secret holding OpenStack credentials + // to be used when reconciling this machine. If not specified, the + // credentials specified in the cluster will be used. // +optional IdentityRef *OpenStackIdentityReference `json:"identityRef,omitempty"` + + // floatingIPPoolRef is a reference to a IPPool that will be assigned + // to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP + // will be assigned to the OpenStackMachine. + // +optional + FloatingIPPoolRef *corev1.TypedLocalObjectReference `json:"floatingIPPoolRef,omitempty"` +} + +type ServerMetadata struct { + // Key is the server metadata key + // +kubebuilder:validation:MaxLength:=255 + // +kubebuilder:validation:Required + Key string `json:"key"` + + // Value is the server metadata value + // +kubebuilder:validation:MaxLength:=255 + // +kubebuilder:validation:Required + Value string `json:"value"` } // OpenStackMachineStatus defines the observed state of OpenStackMachine. @@ -104,6 +118,10 @@ type OpenStackMachineStatus struct { // +optional Ready bool `json:"ready"` + // InstanceID is the OpenStack instance ID for this machine. + // +optional + InstanceID optional.String `json:"instanceID,omitempty"` + // Addresses contains the OpenStack instance associated addresses. Addresses []corev1.NodeAddress `json:"addresses,omitempty"` @@ -111,6 +129,15 @@ type OpenStackMachineStatus struct { // +optional InstanceState *InstanceState `json:"instanceState,omitempty"` + // Resolved contains parts of the machine spec with all external + // references fully resolved. + // +optional + Resolved *ResolvedMachineSpec `json:"resolved,omitempty"` + + // Resources contains references to OpenStack resources created for the machine. + // +optional + Resources *MachineResources `json:"resources,omitempty"` + FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"` // FailureMessage will be set in the event that there is a terminal problem @@ -135,6 +162,8 @@ type OpenStackMachineStatus struct { Conditions clusterv1.Conditions `json:"conditions,omitempty"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true // +kubebuilder:storageversion // +kubebuilder:resource:path=openstackmachines,scope=Namespaced,categories=cluster-api,shortName=osm @@ -177,9 +206,9 @@ func (r *OpenStackMachine) SetConditions(conditions clusterv1.Conditions) { // SetFailure sets the OpenStackMachine status failure reason and failure message. func (r *OpenStackMachine) SetFailure(failureReason errors.MachineStatusError, failureMessage error) { r.Status.FailureReason = &failureReason - r.Status.FailureMessage = pointer.String(failureMessage.Error()) + r.Status.FailureMessage = ptr.To(failureMessage.Error()) } func init() { - SchemeBuilder.Register(&OpenStackMachine{}, &OpenStackMachineList{}) + objectTypes = append(objectTypes, &OpenStackMachine{}, &OpenStackMachineList{}) } diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackmachinetemplate_types.go b/api/v1beta1/openstackmachinetemplate_types.go similarity index 91% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackmachinetemplate_types.go rename to api/v1beta1/openstackmachinetemplate_types.go index 5202234ba2..aff1e7060b 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/openstackmachinetemplate_types.go +++ b/api/v1beta1/openstackmachinetemplate_types.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha7 +package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -25,6 +25,8 @@ type OpenStackMachineTemplateSpec struct { Template OpenStackMachineTemplateResource `json:"template"` } +// +genclient +// +genclient:Namespaced // +kubebuilder:object:root=true // +kubebuilder:storageversion // +kubebuilder:resource:path=openstackmachinetemplates,scope=Namespaced,categories=cluster-api,shortName=osmt @@ -47,5 +49,5 @@ type OpenStackMachineTemplateList struct { } func init() { - SchemeBuilder.Register(&OpenStackMachineTemplate{}, &OpenStackMachineTemplateList{}) + objectTypes = append(objectTypes, &OpenStackMachineTemplate{}, &OpenStackMachineTemplateList{}) } diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go new file mode 100644 index 0000000000..7c13a3662d --- /dev/null +++ b/api/v1beta1/types.go @@ -0,0 +1,909 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "k8s.io/utils/ptr" + + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" +) + +// OpenStackMachineTemplateResource describes the data needed to create a OpenStackMachine from a template. +type OpenStackMachineTemplateResource struct { + // Spec is the specification of the desired behavior of the machine. + Spec OpenStackMachineSpec `json:"spec"` +} + +// ImageParam describes a glance image. It can be specified by ID or filter. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type ImageParam struct { + // ID is the uuid of the image. ID will not be validated before use. + // +kubebuilder:validation:Format:=uuid + // +optional + ID optional.String `json:"id,omitempty"` + + // Filter describes a query for an image. If specified, the combination + // of name and tags must return a single matching image or an error will + // be raised. + // +optional + Filter *ImageFilter `json:"filter,omitempty"` +} + +// ImageFilter describes a query for an image. +// +kubebuilder:validation:MinProperties:=1 +type ImageFilter struct { + // The name of the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised. + // +optional + Name optional.String `json:"name,omitempty"` + + // The tags associated with the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised. + // +listType=set + // +optional + Tags []string `json:"tags,omitempty"` +} + +func (f *ImageFilter) IsZero() bool { + if f == nil { + return true + } + return f.Name == nil && len(f.Tags) == 0 +} + +type ExternalRouterIPParam struct { + // The FixedIP in the corresponding subnet + FixedIP string `json:"fixedIP,omitempty"` + // The subnet in which the FixedIP is used for the Gateway of this router + Subnet SubnetParam `json:"subnet"` +} + +// NeutronTag represents a tag on a Neutron resource. +// It may not be empty and may not contain commas. +// +kubebuilder:validation:Pattern:="^[^,]+$" +// +kubebuilder:validation:MinLength:=1 +type NeutronTag string + +type FilterByNeutronTags struct { + // Tags is a list of tags to filter by. If specified, the resource must + // have all of the tags specified to be included in the result. + // +listType=set + // +optional + Tags []NeutronTag `json:"tags,omitempty"` + + // TagsAny is a list of tags to filter by. If specified, the resource + // must have at least one of the tags specified to be included in the + // result. + // +listType=set + // +optional + TagsAny []NeutronTag `json:"tagsAny,omitempty"` + + // NotTags is a list of tags to filter by. If specified, resources which + // contain all of the given tags will be excluded from the result. + // +listType=set + // +optional + NotTags []NeutronTag `json:"notTags,omitempty"` + + // NotTagsAny is a list of tags to filter by. If specified, resources + // which contain any of the given tags will be excluded from the result. + // +listType=set + // +optional + NotTagsAny []NeutronTag `json:"notTagsAny,omitempty"` +} + +func (f *FilterByNeutronTags) IsZero() bool { + return f == nil || (len(f.Tags) == 0 && len(f.TagsAny) == 0 && len(f.NotTags) == 0 && len(f.NotTagsAny) == 0) +} + +// SecurityGroupParam specifies an OpenStack security group. It may be specified by ID or filter, but not both. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type SecurityGroupParam struct { + // ID is the ID of the security group to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + // +kubebuilder:validation:Format:=uuid + // +optional + ID optional.String `json:"id,omitempty"` + + // Filter specifies a query to select an OpenStack security group. If provided, cannot be empty. + // +optional + Filter *SecurityGroupFilter `json:"filter,omitempty"` +} + +// SecurityGroupFilter specifies a query to select an OpenStack security group. At least one property must be set. +// +kubebuilder:validation:MinProperties:=1 +type SecurityGroupFilter struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + ProjectID string `json:"projectID,omitempty"` + + FilterByNeutronTags `json:",inline"` +} + +func (f *SecurityGroupFilter) IsZero() bool { + if f == nil { + return true + } + return f.Name == "" && + f.Description == "" && + f.ProjectID == "" && + f.FilterByNeutronTags.IsZero() +} + +// NetworkParam specifies an OpenStack network. It may be specified by either ID or Filter, but not both. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type NetworkParam struct { + // ID is the ID of the network to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + // +kubebuilder:validation:Format:=uuid + // +optional + ID optional.String `json:"id,omitempty"` + + // Filter specifies a filter to select an OpenStack network. If provided, cannot be empty. + // +optional + Filter *NetworkFilter `json:"filter,omitempty"` +} + +// NetworkFilter specifies a query to select an OpenStack network. At least one property must be set. +// +kubebuilder:validation:MinProperties:=1 +type NetworkFilter struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + ProjectID string `json:"projectID,omitempty"` + + FilterByNeutronTags `json:",inline"` +} + +func (networkFilter *NetworkFilter) IsZero() bool { + if networkFilter == nil { + return true + } + return networkFilter.Name == "" && + networkFilter.Description == "" && + networkFilter.ProjectID == "" && + networkFilter.FilterByNeutronTags.IsZero() +} + +// SubnetParam specifies an OpenStack subnet to use. It may be specified by either ID or filter, but not both. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type SubnetParam struct { + // ID is the uuid of the subnet. It will not be validated. + // +kubebuilder:validation:Format:=uuid + // +optional + ID optional.String `json:"id,omitempty"` + + // Filter specifies a filter to select the subnet. It must match exactly one subnet. + // +optional + Filter *SubnetFilter `json:"filter,omitempty"` +} + +// SubnetFilter specifies a filter to select a subnet. At least one parameter must be specified. +// +kubebuilder:validation:MinProperties:=1 +type SubnetFilter struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + ProjectID string `json:"projectID,omitempty"` + IPVersion int `json:"ipVersion,omitempty"` + GatewayIP string `json:"gatewayIP,omitempty"` + CIDR string `json:"cidr,omitempty"` + IPv6AddressMode string `json:"ipv6AddressMode,omitempty"` + IPv6RAMode string `json:"ipv6RAMode,omitempty"` + + FilterByNeutronTags `json:",inline"` +} + +func (subnetFilter *SubnetFilter) IsZero() bool { + if subnetFilter == nil { + return true + } + return subnetFilter.Name == "" && + subnetFilter.Description == "" && + subnetFilter.ProjectID == "" && + subnetFilter.IPVersion == 0 && + subnetFilter.GatewayIP == "" && + subnetFilter.CIDR == "" && + subnetFilter.IPv6AddressMode == "" && + subnetFilter.IPv6RAMode == "" && + subnetFilter.FilterByNeutronTags.IsZero() +} + +// RouterParam specifies an OpenStack router to use. It may be specified by either ID or filter, but not both. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type RouterParam struct { + // ID is the ID of the router to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + // +kubebuilder:validation:Format:=uuid + // +optional + ID optional.String `json:"id,omitempty"` + + // Filter specifies a filter to select an OpenStack router. If provided, cannot be empty. + Filter *RouterFilter `json:"filter,omitempty"` +} + +// RouterFilter specifies a query to select an OpenStack router. At least one property must be set. +// +kubebuilder:validation:MinProperties:=1 +type RouterFilter struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + ProjectID string `json:"projectID,omitempty"` + + FilterByNeutronTags `json:",inline"` +} + +func (f *RouterFilter) IsZero() bool { + if f == nil { + return true + } + return f.Name == "" && + f.Description == "" && + f.ProjectID == "" && + f.FilterByNeutronTags.IsZero() +} + +type SubnetSpec struct { + // CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24. + // This field is required when defining a subnet. + // +required + CIDR string `json:"cidr"` + + // DNSNameservers holds a list of DNS server addresses that will be provided when creating + // the subnet. These addresses need to have the same IP version as CIDR. + DNSNameservers []string `json:"dnsNameservers,omitempty"` + + // AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. + // If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from + // outside of these ranges manually. + AllocationPools []AllocationPool `json:"allocationPools,omitempty"` +} + +type AllocationPool struct { + // Start represents the start of the AllocationPool, that is the lowest IP of the pool. + // +required + Start string `json:"start"` + + // End represents the end of the AlloctionPool, that is the highest IP of the pool. + // +required + End string `json:"end"` +} + +type PortOpts struct { + // Network is a query for an openstack network that the port will be created or discovered on. + // This will fail if the query returns more than one network. + // +optional + Network *NetworkParam `json:"network,omitempty"` + + // Description is a human-readable description for the port. + // +optional + Description optional.String `json:"description,omitempty"` + + // NameSuffix will be appended to the name of the port if specified. If unspecified, instead the 0-based index of the port in the list is used. + // +optional + NameSuffix optional.String `json:"nameSuffix,omitempty"` + + // FixedIPs is a list of pairs of subnet and/or IP address to assign to the port. If specified, these must be subnets of the port's network. + // +optional + // +listType=atomic + FixedIPs []FixedIP `json:"fixedIPs,omitempty"` + + // SecurityGroups is a list of the names, uuids, filters or any combination these of the security groups to assign to the instance. + // +optional + // +listType=atomic + SecurityGroups []SecurityGroupParam `json:"securityGroups,omitempty"` + + // Tags applied to the port (and corresponding trunk, if a trunk is configured.) + // These tags are applied in addition to the instance's tags, which will also be applied to the port. + // +listType=set + // +optional + Tags []string `json:"tags,omitempty"` + + // Trunk specifies whether trunking is enabled at the port level. If not + // provided the value is inherited from the machine, or false for a + // bastion host. + // +optional + Trunk *bool `json:"trunk,omitempty"` + + ResolvedPortSpecFields `json:",inline"` +} + +// ResolvePortSpecFields is a convenience struct containing all fields of a +// PortOpts which don't contain references which need to be resolved, and can +// therefore be shared with ResolvedPortSpec. +type ResolvedPortSpecFields struct { + // AdminStateUp specifies whether the port should be created in the up (true) or down (false) state. The default is up. + // +optional + AdminStateUp *bool `json:"adminStateUp,omitempty"` + + // MACAddress specifies the MAC address of the port. If not specified, the MAC address will be generated. + // +optional + MACAddress optional.String `json:"macAddress,omitempty"` + + // AllowedAddressPairs is a list of address pairs which Neutron will + // allow the port to send traffic from in addition to the port's + // addresses. If not specified, the MAC Address will be the MAC Address + // of the port. Depending on the configuration of Neutron, it may be + // supported to specify a CIDR instead of a specific IP address. + // +optional + AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"` + + // HostID specifies the ID of the host where the port resides. + // +optional + HostID optional.String `json:"hostID,omitempty"` + + // VNICType specifies the type of vNIC which this port should be + // attached to. This is used to determine which mechanism driver(s) to + // be used to bind the port. The valid values are normal, macvtap, + // direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + // remote-managed, although these values will not be validated in this + // API to ensure compatibility with future neutron changes or custom + // implementations. What type of vNIC is actually available depends on + // deployments. If not specified, the Neutron default value is used. + // +optional + VNICType optional.String `json:"vnicType,omitempty"` + + // Profile is a set of key-value pairs that are used for binding + // details. We intentionally don't expose this as a map[string]string + // because we only want to enable the users to set the values of the + // keys that are known to work in OpenStack Networking API. See + // https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + // To set profiles, your tenant needs permissions rule:create_port, and + // rule:create_port:binding:profile + // +optional + Profile *BindingProfile `json:"profile,omitempty"` + + // DisablePortSecurity enables or disables the port security when set. + // When not set, it takes the value of the corresponding field at the network level. + // +optional + DisablePortSecurity *bool `json:"disablePortSecurity,omitempty"` + + // PropageteUplinkStatus enables or disables the propagate uplink status on the port. + // +optional + PropagateUplinkStatus *bool `json:"propagateUplinkStatus,omitempty"` + + // Value specs are extra parameters to include in the API request with OpenStack. + // This is an extension point for the API, so what they do and if they are supported, + // depends on the specific OpenStack implementation. + // +optional + // +listType=map + // +listMapKey=name + ValueSpecs []ValueSpec `json:"valueSpecs,omitempty"` +} + +// ResolvedPortSpec is a PortOpts with all contained references fully resolved. +type ResolvedPortSpec struct { + // Name is the name of the port. + Name string `json:"name"` + + // Description is a human-readable description for the port. + Description string `json:"description"` + + // NetworkID is the ID of the network the port will be created in. + NetworkID string `json:"networkID"` + + // Tags applied to the port (and corresponding trunk, if a trunk is configured.) + // +listType=set + // +optional + Tags []string `json:"tags,omitempty"` + + // Trunk specifies whether trunking is enabled at the port level. + // +optional + Trunk optional.Bool `json:"trunk,omitempty"` + + // FixedIPs is a list of pairs of subnet and/or IP address to assign to the port. If specified, these must be subnets of the port's network. + // +optional + // +listType=atomic + FixedIPs []ResolvedFixedIP `json:"fixedIPs,omitempty"` + + // SecurityGroups is a list of security group IDs to assign to the port. + // +optional + // +listType=atomic + SecurityGroups []string `json:"securityGroups,omitempty"` + + ResolvedPortSpecFields `json:",inline"` +} + +type PortStatus struct { + // ID is the unique identifier of the port. + // +required + ID string `json:"id"` +} + +type BindingProfile struct { + // OVSHWOffload enables or disables the OVS hardware offload feature. + // +optional + OVSHWOffload *bool `json:"ovsHWOffload,omitempty"` + + // TrustedVF enables or disables the “trusted mode” for the VF. + // +optional + TrustedVF *bool `json:"trustedVF,omitempty"` +} + +type FixedIP struct { + // Subnet is an openstack subnet query that will return the id of a subnet to create + // the fixed IP of a port in. This query must not return more than one subnet. + // +optional + Subnet *SubnetParam `json:"subnet,omitempty"` + + // IPAddress is a specific IP address to assign to the port. If Subnet + // is also specified, IPAddress must be a valid IP address in the + // subnet. If Subnet is not specified, IPAddress must be a valid IP + // address in any subnet of the port's network. + // +optional + IPAddress optional.String `json:"ipAddress,omitempty"` +} + +// ResolvedFixedIP is a FixedIP with the Subnet resolved to an ID. +type ResolvedFixedIP struct { + // SubnetID is the id of a subnet to create the fixed IP of a port in. + // +optional + SubnetID optional.String `json:"subnet,omitempty"` + + // IPAddress is a specific IP address to assign to the port. If SubnetID + // is also specified, IPAddress must be a valid IP address in the + // subnet. If Subnet is not specified, IPAddress must be a valid IP + // address in any subnet of the port's network. + // +optional + IPAddress optional.String `json:"ipAddress,omitempty"` +} + +type AddressPair struct { + // IPAddress is the IP address of the allowed address pair. Depending on + // the configuration of Neutron, it may be supported to specify a CIDR + // instead of a specific IP address. + // +kubebuilder:validation:Required + IPAddress string `json:"ipAddress"` + + // MACAddress is the MAC address of the allowed address pair. If not + // specified, the MAC address will be the MAC address of the port. + // +optional + MACAddress optional.String `json:"macAddress,omitempty"` +} + +type BastionStatus struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + SSHKeyName string `json:"sshKeyName,omitempty"` + State InstanceState `json:"state,omitempty"` + IP string `json:"ip,omitempty"` + FloatingIP string `json:"floatingIP,omitempty"` + + // Resolved contains parts of the bastion's machine spec with all + // external references fully resolved. + // +optional + Resolved *ResolvedMachineSpec `json:"resolved,omitempty"` + + // Resources contains references to OpenStack resources created for the bastion. + // +optional + Resources *MachineResources `json:"resources,omitempty"` +} + +type RootVolume struct { + // SizeGiB is the size of the block device in gibibytes (GiB). + // +kubebuilder:validation:Required + // +kubebuilder:validation:Minimum:=1 + SizeGiB int `json:"sizeGiB"` + + BlockDeviceVolume `json:",inline"` +} + +// BlockDeviceStorage is the storage type of a block device to create and +// contains additional storage options. +// +union +// +//nolint:godot +type BlockDeviceStorage struct { + // Type is the type of block device to create. + // This can be either "Volume" or "Local". + // +unionDiscriminator + Type BlockDeviceType `json:"type"` + + // Volume contains additional storage options for a volume block device. + // +optional + // +unionMember,optional + Volume *BlockDeviceVolume `json:"volume,omitempty"` +} + +// BlockDeviceVolume contains additional storage options for a volume block device. +type BlockDeviceVolume struct { + // Type is the Cinder volume type of the volume. + // If omitted, the default Cinder volume type that is configured in the OpenStack cloud + // will be used. + // +optional + Type string `json:"type,omitempty"` + + // AvailabilityZone is the volume availability zone to create the volume + // in. If not specified, the volume will be created without an explicit + // availability zone. + // +optional + AvailabilityZone *VolumeAvailabilityZone `json:"availabilityZone,omitempty"` +} + +// VolumeAZSource specifies where to obtain the availability zone for a volume. +// +kubebuilder:validation:Enum=Name;Machine +type VolumeAZSource string + +const ( + VolumeAZFromName VolumeAZSource = "Name" + VolumeAZFromMachine VolumeAZSource = "Machine" +) + +// VolumeAZName is the name of a volume availability zone. It may not contain spaces. +// +kubebuilder:validation:Pattern:="^[^ ]+$" +// +kubebuilder:validation:MinLength:=1 +type VolumeAZName string + +// VolumeAvailabilityZone specifies the availability zone for a volume. +// +kubebuilder:validation:XValidation:rule="!has(self.from) || self.from == 'Name' ? has(self.name) : !has(self.name)",message="name is required when from is 'Name' or default" +type VolumeAvailabilityZone struct { + // From specifies where we will obtain the availability zone for the + // volume. The options are "Name" and "Machine". If "Name" is specified + // then the Name field must also be specified. If "Machine" is specified + // the volume will use the value of FailureDomain, if any, from the + // associated Machine. + // +kubebuilder:default:=Name + // +optional + From VolumeAZSource `json:"from,omitempty"` + + // Name is the name of a volume availability zone to use. It is required + // if From is "Name". The volume availability zone name may not contain + // spaces. + // +optional + Name *VolumeAZName `json:"name,omitempty"` +} + +// AdditionalBlockDevice is a block device to attach to the server. +type AdditionalBlockDevice struct { + // Name of the block device in the context of a machine. + // If the block device is a volume, the Cinder volume will be named + // as a combination of the machine name and this name. + // Also, this name will be used for tagging the block device. + // Information about the block device tag can be obtained from the OpenStack + // metadata API or the config drive. + // Name cannot be 'root', which is reserved for the root volume. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // SizeGiB is the size of the block device in gibibytes (GiB). + // +kubebuilder:validation:Required + // +kubebuilder:validation:Minimum:=1 + SizeGiB int `json:"sizeGiB"` + + // Storage specifies the storage type of the block device and + // additional storage options. + Storage BlockDeviceStorage `json:"storage"` +} + +// ServerGroupParam specifies an OpenStack server group. It may be specified by ID or filter, but not both. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type ServerGroupParam struct { + // ID is the ID of the server group to use. + // +kubebuilder:validation:Format:=uuid + ID optional.String `json:"id,omitempty"` + + // Filter specifies a query to select an OpenStack server group. If provided, it cannot be empty. + Filter *ServerGroupFilter `json:"filter,omitempty"` +} + +// ServerGroupFilter specifies a query to select an OpenStack server group. At least one property must be set. +// +kubebuilder:validation:MinProperties:=1 +type ServerGroupFilter struct { + // Name is the name of a server group to look for. + Name optional.String `json:"name,omitempty"` +} + +func (f *ServerGroupFilter) IsZero() bool { + if f == nil { + return true + } + return f.Name == nil +} + +// BlockDeviceType defines the type of block device to create. +type BlockDeviceType string + +const ( + // LocalBlockDevice is an ephemeral block device attached to the server. + LocalBlockDevice BlockDeviceType = "Local" + + // VolumeBlockDevice is a volume block device attached to the server. + VolumeBlockDevice BlockDeviceType = "Volume" +) + +// NetworkStatus contains basic information about an existing neutron network. +type NetworkStatus struct { + Name string `json:"name"` + ID string `json:"id"` + + //+optional + Tags []string `json:"tags,omitempty"` +} + +// NetworkStatusWithSubnets represents basic information about an existing neutron network and an associated set of subnets. +type NetworkStatusWithSubnets struct { + NetworkStatus `json:",inline"` + + // Subnets is a list of subnets associated with the default cluster network. Machines which use the default cluster network will get an address from all of these subnets. + Subnets []Subnet `json:"subnets,omitempty"` +} + +// Subnet represents basic information about the associated OpenStack Neutron Subnet. +type Subnet struct { + Name string `json:"name"` + ID string `json:"id"` + + CIDR string `json:"cidr"` + + //+optional + Tags []string `json:"tags,omitempty"` +} + +// Router represents basic information about the associated OpenStack Neutron Router. +type Router struct { + Name string `json:"name"` + ID string `json:"id"` + //+optional + Tags []string `json:"tags,omitempty"` + //+optional + IPs []string `json:"ips,omitempty"` +} + +// LoadBalancer represents basic information about the associated OpenStack LoadBalancer. +type LoadBalancer struct { + Name string `json:"name"` + ID string `json:"id"` + IP string `json:"ip"` + InternalIP string `json:"internalIP"` + //+optional + AllowedCIDRs []string `json:"allowedCIDRs,omitempty"` + //+optional + Tags []string `json:"tags,omitempty"` + // LoadBalancerNetwork contains information about network and/or subnets which the + // loadbalancer is allocated on. + // If subnets are specified within the LoadBalancerNetwork currently only the first + // subnet in the list is taken into account. + // +optional + LoadBalancerNetwork *NetworkStatusWithSubnets `json:"loadBalancerNetwork,omitempty"` +} + +// SecurityGroupStatus represents the basic information of the associated +// OpenStack Neutron Security Group. +type SecurityGroupStatus struct { + // name of the security group + // +kubebuilder:validation:Required + Name string `json:"name"` + + // id of the security group + // +kubebuilder:validation:Required + ID string `json:"id"` +} + +// SecurityGroupRuleSpec represent the basic information of the associated OpenStack +// Security Group Role. +// For now this is only used for the allNodesSecurityGroupRules but when we add +// other security groups, we'll need to add a validation because +// Remote* fields are mutually exclusive. +type SecurityGroupRuleSpec struct { + // name of the security group rule. + // It's used to identify the rule so it can be patched and will not be sent to the OpenStack API. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // description of the security group rule. + // +optional + Description *string `json:"description,omitempty"` + + // direction in which the security group rule is applied. The only values + // allowed are "ingress" or "egress". For a compute instance, an ingress + // security group rule is applied to incoming (ingress) traffic for that + // instance. An egress rule is applied to traffic leaving the instance. + // +kubebuilder:validation:Required + // +kubebuilder:validation:enum=ingress;egress + Direction string `json:"direction"` + + // etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the + // ingress or egress rules. + // +kubebuilder:validation:enum=IPv4;IPv6 + // +optional + EtherType *string `json:"etherType,omitempty"` + + // portRangeMin is a number in the range that is matched by the security group + // rule. If the protocol is TCP or UDP, this value must be less than or equal + // to the value of the portRangeMax attribute. + // +optional + PortRangeMin *int `json:"portRangeMin,omitempty"` + + // portRangeMax is a number in the range that is matched by the security group + // rule. The portRangeMin attribute constrains the portRangeMax attribute. + // +optional + PortRangeMax *int `json:"portRangeMax,omitempty"` + + // protocol is the protocol that is matched by the security group rule. + // +optional + Protocol *string `json:"protocol,omitempty"` + + // remoteGroupID is the remote group ID to be associated with this security group rule. + // You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + // +optional + RemoteGroupID *string `json:"remoteGroupID,omitempty"` + + // remoteIPPrefix is the remote IP prefix to be associated with this security group rule. + // You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + // +optional + RemoteIPPrefix *string `json:"remoteIPPrefix,omitempty"` + + // remoteManagedGroups is the remote managed groups to be associated with this security group rule. + // You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + // +optional + RemoteManagedGroups []ManagedSecurityGroupName `json:"remoteManagedGroups,omitempty"` +} + +// +kubebuilder:validation:Enum=bastion;controlplane;worker +type ManagedSecurityGroupName string + +func (m ManagedSecurityGroupName) String() string { + return string(m) +} + +// InstanceState describes the state of an OpenStack instance. +type InstanceState string + +var ( + // InstanceStateBuild is the string representing an instance in a build state. + InstanceStateBuild = InstanceState("BUILD") + + // InstanceStateActive is the string representing an instance in an active state. + InstanceStateActive = InstanceState("ACTIVE") + + // InstanceStateError is the string representing an instance in an error state. + InstanceStateError = InstanceState("ERROR") + + // InstanceStateStopped is the string representing an instance in a stopped state. + InstanceStateStopped = InstanceState("STOPPED") + + // InstanceStateShutoff is the string representing an instance in a shutoff state. + InstanceStateShutoff = InstanceState("SHUTOFF") + + // InstanceStateDeleted is the string representing an instance in a deleted state. + InstanceStateDeleted = InstanceState("DELETED") + + // InstanceStateUndefined is the string representing an undefined instance state. + InstanceStateUndefined = InstanceState("") +) + +// Bastion represents basic information about the bastion node. If you enable bastion, the spec has to be specified. +// +kubebuilder:validation:XValidation:rule="!self.enabled || has(self.spec)",message="spec is required if bastion is enabled" +type Bastion struct { + // Enabled means that bastion is enabled. The bastion is enabled by + // default if this field is not specified. Set this field to false to disable the + // bastion. + // + // It is not currently possible to remove the bastion from the cluster + // spec without first disabling it by setting this field to false and + // waiting until the bastion has been deleted. + // +kubebuilder:default:=true + // +optional + Enabled optional.Bool `json:"enabled,omitempty"` + + // Spec for the bastion itself + Spec *OpenStackMachineSpec `json:"spec,omitempty"` + + // AvailabilityZone is the failure domain that will be used to create the Bastion Spec. + //+optional + AvailabilityZone optional.String `json:"availabilityZone,omitempty"` + + // FloatingIP which will be associated to the bastion machine. It's the IP address, not UUID. + // The floating IP should already exist and should not be associated with a port. If FIP of this address does not + // exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so. + //+optional + //+kubebuilder:validation:Format:=ipv4 + FloatingIP optional.String `json:"floatingIP,omitempty"` +} + +func (b *Bastion) IsEnabled() bool { + if b == nil { + return false + } + return b.Enabled == nil || *b.Enabled +} + +type APIServerLoadBalancer struct { + // Enabled defines whether a load balancer should be created. This value + // defaults to true if an APIServerLoadBalancer is given. + // + // There is no reason to set this to false. To disable creation of the + // API server loadbalancer, omit the APIServerLoadBalancer field in the + // cluster spec instead. + // + // +kubebuilder:validation:Required + // +kubebuilder:default:=true + Enabled *bool `json:"enabled"` + + // AdditionalPorts adds additional tcp ports to the load balancer. + // +optional + // +listType=set + AdditionalPorts []int `json:"additionalPorts,omitempty"` + + // AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs. + // +optional + // +listType=set + AllowedCIDRs []string `json:"allowedCIDRs,omitempty"` + + // Provider specifies name of a specific Octavia provider to use for the + // API load balancer. The Octavia default will be used if it is not + // specified. + // +optional + Provider optional.String `json:"provider,omitempty"` + + // Network defines which network should the load balancer be allocated on. + //+optional + Network *NetworkParam `json:"network,omitempty"` + + // Subnets define which subnets should the load balancer be allocated on. + // It is expected that subnets are located on the network specified in this resource. + // Only the first element is taken into account. + // +optional + // +listType=atomic + // kubebuilder:validation:MaxLength:=2 + Subnets []SubnetParam `json:"subnets,omitempty"` + + // AvailabilityZone is the failure domain that will be used to create the APIServerLoadBalancer Spec. + //+optional + AvailabilityZone optional.String `json:"availabilityZone,omitempty"` +} + +func (s *APIServerLoadBalancer) IsZero() bool { + return s == nil || ((s.Enabled == nil || !*s.Enabled) && len(s.AdditionalPorts) == 0 && len(s.AllowedCIDRs) == 0 && ptr.Deref(s.Provider, "") == "") +} + +func (s *APIServerLoadBalancer) IsEnabled() bool { + // The CRD default value for Enabled is true, so if the field is nil, it should be considered as true. + return s != nil && (s.Enabled == nil || *s.Enabled) +} + +// ResolvedMachineSpec contains resolved references to resources required by the machine. +type ResolvedMachineSpec struct { + // ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter. + // +optional + ServerGroupID string `json:"serverGroupID,omitempty"` + + // ImageID is the ID of the image to use for the machine and is calculated based on ImageFilter. + // +optional + ImageID string `json:"imageID,omitempty"` + + // Ports is the fully resolved list of ports to create for the machine. + // +optional + Ports []ResolvedPortSpec `json:"ports,omitempty"` +} + +type MachineResources struct { + // Ports is the status of the ports created for the machine. + // +optional + Ports []PortStatus `json:"ports,omitempty"` +} + +// ValueSpec represents a single value_spec key-value pair. +type ValueSpec struct { + // Name is the name of the key-value pair. + // This is just for identifying the pair and will not be sent to the OpenStack API. + // +kubebuilder:validation:Required + Name string `json:"name"` + // Key is the key in the key-value pair. + // +kubebuilder:validation:Required + Key string `json:"key"` + // Value is the value in the key-value pair. + // +kubebuilder:validation:Required + Value string `json:"value"` +} diff --git a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go similarity index 59% rename from openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/zz_generated.deepcopy.go rename to api/v1beta1/zz_generated.deepcopy.go index 1d81a83410..e0e7e28ad2 100644 --- a/openshift/vendor/sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,18 +18,23 @@ limitations under the License. // Code generated by controller-gen. DO NOT EDIT. -package v1alpha7 +package v1beta1 import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/cluster-api/api/v1beta1" + apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/errors" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *APIServerLoadBalancer) DeepCopyInto(out *APIServerLoadBalancer) { *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } if in.AdditionalPorts != nil { in, out := &in.AdditionalPorts, &out.AdditionalPorts *out = make([]int, len(*in)) @@ -40,6 +45,28 @@ func (in *APIServerLoadBalancer) DeepCopyInto(out *APIServerLoadBalancer) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Provider != nil { + in, out := &in.Provider, &out.Provider + *out = new(string) + **out = **in + } + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkParam) + (*in).DeepCopyInto(*out) + } + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]SubnetParam, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AvailabilityZone != nil { + in, out := &in.AvailabilityZone, &out.AvailabilityZone + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServerLoadBalancer. @@ -71,6 +98,11 @@ func (in *AdditionalBlockDevice) DeepCopy() *AdditionalBlockDevice { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AddressPair) DeepCopyInto(out *AddressPair) { *out = *in + if in.MACAddress != nil { + in, out := &in.MACAddress, &out.MACAddress + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressPair. @@ -83,10 +115,44 @@ func (in *AddressPair) DeepCopy() *AddressPair { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllocationPool) DeepCopyInto(out *AllocationPool) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllocationPool. +func (in *AllocationPool) DeepCopy() *AllocationPool { + if in == nil { + return nil + } + out := new(AllocationPool) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Bastion) DeepCopyInto(out *Bastion) { *out = *in - in.Instance.DeepCopyInto(&out.Instance) + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(OpenStackMachineSpec) + (*in).DeepCopyInto(*out) + } + if in.AvailabilityZone != nil { + in, out := &in.AvailabilityZone, &out.AvailabilityZone + *out = new(string) + **out = **in + } + if in.FloatingIP != nil { + in, out := &in.FloatingIP, &out.FloatingIP + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Bastion. @@ -102,6 +168,16 @@ func (in *Bastion) DeepCopy() *Bastion { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BastionStatus) DeepCopyInto(out *BastionStatus) { *out = *in + if in.Resolved != nil { + in, out := &in.Resolved, &out.Resolved + *out = new(ResolvedMachineSpec) + (*in).DeepCopyInto(*out) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(MachineResources) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionStatus. @@ -117,6 +193,16 @@ func (in *BastionStatus) DeepCopy() *BastionStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BindingProfile) DeepCopyInto(out *BindingProfile) { *out = *in + if in.OVSHWOffload != nil { + in, out := &in.OVSHWOffload, &out.OVSHWOffload + *out = new(bool) + **out = **in + } + if in.TrustedVF != nil { + in, out := &in.TrustedVF, &out.TrustedVF + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BindingProfile. @@ -135,7 +221,7 @@ func (in *BlockDeviceStorage) DeepCopyInto(out *BlockDeviceStorage) { if in.Volume != nil { in, out := &in.Volume, &out.Volume *out = new(BlockDeviceVolume) - **out = **in + (*in).DeepCopyInto(*out) } } @@ -152,6 +238,11 @@ func (in *BlockDeviceStorage) DeepCopy() *BlockDeviceStorage { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BlockDeviceVolume) DeepCopyInto(out *BlockDeviceVolume) { *out = *in + if in.AvailabilityZone != nil { + in, out := &in.AvailabilityZone, &out.AvailabilityZone + *out = new(VolumeAvailabilityZone) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceVolume. @@ -167,7 +258,7 @@ func (in *BlockDeviceVolume) DeepCopy() *BlockDeviceVolume { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExternalRouterIPParam) DeepCopyInto(out *ExternalRouterIPParam) { *out = *in - out.Subnet = in.Subnet + in.Subnet.DeepCopyInto(&out.Subnet) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalRouterIPParam. @@ -180,12 +271,52 @@ func (in *ExternalRouterIPParam) DeepCopy() *ExternalRouterIPParam { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FilterByNeutronTags) DeepCopyInto(out *FilterByNeutronTags) { + *out = *in + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]NeutronTag, len(*in)) + copy(*out, *in) + } + if in.TagsAny != nil { + in, out := &in.TagsAny, &out.TagsAny + *out = make([]NeutronTag, len(*in)) + copy(*out, *in) + } + if in.NotTags != nil { + in, out := &in.NotTags, &out.NotTags + *out = make([]NeutronTag, len(*in)) + copy(*out, *in) + } + if in.NotTagsAny != nil { + in, out := &in.NotTagsAny, &out.NotTagsAny + *out = make([]NeutronTag, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FilterByNeutronTags. +func (in *FilterByNeutronTags) DeepCopy() *FilterByNeutronTags { + if in == nil { + return nil + } + out := new(FilterByNeutronTags) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FixedIP) DeepCopyInto(out *FixedIP) { *out = *in if in.Subnet != nil { in, out := &in.Subnet, &out.Subnet - *out = new(SubnetFilter) + *out = new(SubnetParam) + (*in).DeepCopyInto(*out) + } + if in.IPAddress != nil { + in, out := &in.IPAddress, &out.IPAddress + *out = new(string) **out = **in } } @@ -200,6 +331,56 @@ func (in *FixedIP) DeepCopy() *FixedIP { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageFilter) DeepCopyInto(out *ImageFilter) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageFilter. +func (in *ImageFilter) DeepCopy() *ImageFilter { + if in == nil { + return nil + } + out := new(ImageFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageParam) DeepCopyInto(out *ImageParam) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(ImageFilter) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageParam. +func (in *ImageParam) DeepCopy() *ImageParam { + if in == nil { + return nil + } + out := new(ImageParam) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { *out = *in @@ -213,6 +394,11 @@ func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.LoadBalancerNetwork != nil { + in, out := &in.LoadBalancerNetwork, &out.LoadBalancerNetwork + *out = new(NetworkStatusWithSubnets) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancer. @@ -225,9 +411,52 @@ func (in *LoadBalancer) DeepCopy() *LoadBalancer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineResources) DeepCopyInto(out *MachineResources) { + *out = *in + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]PortStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineResources. +func (in *MachineResources) DeepCopy() *MachineResources { + if in == nil { + return nil + } + out := new(MachineResources) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedSecurityGroups) DeepCopyInto(out *ManagedSecurityGroups) { + *out = *in + if in.AllNodesSecurityGroupRules != nil { + in, out := &in.AllNodesSecurityGroupRules, &out.AllNodesSecurityGroupRules + *out = make([]SecurityGroupRuleSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedSecurityGroups. +func (in *ManagedSecurityGroups) DeepCopy() *ManagedSecurityGroups { + if in == nil { + return nil + } + out := new(ManagedSecurityGroups) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkFilter) DeepCopyInto(out *NetworkFilter) { *out = *in + in.FilterByNeutronTags.DeepCopyInto(&out.FilterByNeutronTags) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkFilter. @@ -240,6 +469,31 @@ func (in *NetworkFilter) DeepCopy() *NetworkFilter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkParam) DeepCopyInto(out *NetworkParam) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(NetworkFilter) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkParam. +func (in *NetworkParam) DeepCopy() *NetworkParam { + if in == nil { + return nil + } + out := new(NetworkParam) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkStatus) DeepCopyInto(out *NetworkStatus) { *out = *in @@ -345,45 +599,113 @@ func (in *OpenStackClusterList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) { *out = *in + if in.ManagedSubnets != nil { + in, out := &in.ManagedSubnets, &out.ManagedSubnets + *out = make([]SubnetSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.Router != nil { in, out := &in.Router, &out.Router - *out = new(RouterFilter) - **out = **in + *out = new(RouterParam) + (*in).DeepCopyInto(*out) } - out.Network = in.Network - out.Subnet = in.Subnet - if in.DNSNameservers != nil { - in, out := &in.DNSNameservers, &out.DNSNameservers - *out = make([]string, len(*in)) - copy(*out, *in) + if in.Network != nil { + in, out := &in.Network, &out.Network + *out = new(NetworkParam) + (*in).DeepCopyInto(*out) + } + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]SubnetParam, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.NetworkMTU != nil { + in, out := &in.NetworkMTU, &out.NetworkMTU + *out = new(int) + **out = **in } if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs *out = make([]ExternalRouterIPParam, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ExternalNetwork != nil { + in, out := &in.ExternalNetwork, &out.ExternalNetwork + *out = new(NetworkParam) + (*in).DeepCopyInto(*out) + } + if in.DisableExternalNetwork != nil { + in, out := &in.DisableExternalNetwork, &out.DisableExternalNetwork + *out = new(bool) + **out = **in + } + if in.APIServerLoadBalancer != nil { + in, out := &in.APIServerLoadBalancer, &out.APIServerLoadBalancer + *out = new(APIServerLoadBalancer) + (*in).DeepCopyInto(*out) + } + if in.DisableAPIServerFloatingIP != nil { + in, out := &in.DisableAPIServerFloatingIP, &out.DisableAPIServerFloatingIP + *out = new(bool) + **out = **in + } + if in.APIServerFloatingIP != nil { + in, out := &in.APIServerFloatingIP, &out.APIServerFloatingIP + *out = new(string) + **out = **in + } + if in.APIServerFixedIP != nil { + in, out := &in.APIServerFixedIP, &out.APIServerFixedIP + *out = new(string) + **out = **in + } + if in.APIServerPort != nil { + in, out := &in.APIServerPort, &out.APIServerPort + *out = new(int) + **out = **in + } + if in.ManagedSecurityGroups != nil { + in, out := &in.ManagedSecurityGroups, &out.ManagedSecurityGroups + *out = new(ManagedSecurityGroups) + (*in).DeepCopyInto(*out) + } + if in.DisablePortSecurity != nil { + in, out := &in.DisablePortSecurity, &out.DisablePortSecurity + *out = new(bool) + **out = **in } - in.APIServerLoadBalancer.DeepCopyInto(&out.APIServerLoadBalancer) if in.Tags != nil { in, out := &in.Tags, &out.Tags *out = make([]string, len(*in)) copy(*out, *in) } - out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + if in.ControlPlaneEndpoint != nil { + in, out := &in.ControlPlaneEndpoint, &out.ControlPlaneEndpoint + *out = new(apiv1beta1.APIEndpoint) + **out = **in + } if in.ControlPlaneAvailabilityZones != nil { in, out := &in.ControlPlaneAvailabilityZones, &out.ControlPlaneAvailabilityZones *out = make([]string, len(*in)) copy(*out, *in) } + if in.ControlPlaneOmitAvailabilityZone != nil { + in, out := &in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone + *out = new(bool) + **out = **in + } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion *out = new(Bastion) (*in).DeepCopyInto(*out) } - if in.IdentityRef != nil { - in, out := &in.IdentityRef, &out.IdentityRef - *out = new(OpenStackIdentityReference) - **out = **in - } + out.IdentityRef = in.IdentityRef } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterSpec. @@ -421,30 +743,30 @@ func (in *OpenStackClusterStatus) DeepCopyInto(out *OpenStackClusterStatus) { } if in.FailureDomains != nil { in, out := &in.FailureDomains, &out.FailureDomains - *out = make(v1beta1.FailureDomains, len(*in)) + *out = make(apiv1beta1.FailureDomains, len(*in)) for key, val := range *in { (*out)[key] = *val.DeepCopy() } } if in.ControlPlaneSecurityGroup != nil { in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup - *out = new(SecurityGroup) - (*in).DeepCopyInto(*out) + *out = new(SecurityGroupStatus) + **out = **in } if in.WorkerSecurityGroup != nil { in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup - *out = new(SecurityGroup) - (*in).DeepCopyInto(*out) + *out = new(SecurityGroupStatus) + **out = **in } if in.BastionSecurityGroup != nil { in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup - *out = new(SecurityGroup) - (*in).DeepCopyInto(*out) + *out = new(SecurityGroupStatus) + **out = **in } if in.Bastion != nil { in, out := &in.Bastion, &out.Bastion *out = new(BastionStatus) - **out = **in + (*in).DeepCopyInto(*out) } if in.FailureReason != nil { in, out := &in.FailureReason, &out.FailureReason @@ -640,11 +962,7 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) { *out = new(string) **out = **in } - if in.InstanceID != nil { - in, out := &in.InstanceID, &out.InstanceID - *out = new(string) - **out = **in - } + in.Image.DeepCopyInto(&out.Image) if in.Ports != nil { in, out := &in.Ports, &out.Ports *out = make([]PortOpts, len(*in)) @@ -654,8 +972,10 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) { } if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]SecurityGroupFilter, len(*in)) - copy(*out, *in) + *out = make([]SecurityGroupParam, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.Tags != nil { in, out := &in.Tags, &out.Tags @@ -664,10 +984,8 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) { } if in.ServerMetadata != nil { in, out := &in.ServerMetadata, &out.ServerMetadata - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } + *out = make([]ServerMetadata, len(*in)) + copy(*out, *in) } if in.ConfigDrive != nil { in, out := &in.ConfigDrive, &out.ConfigDrive @@ -677,7 +995,7 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) { if in.RootVolume != nil { in, out := &in.RootVolume, &out.RootVolume *out = new(RootVolume) - **out = **in + (*in).DeepCopyInto(*out) } if in.AdditionalBlockDevices != nil { in, out := &in.AdditionalBlockDevices, &out.AdditionalBlockDevices @@ -686,11 +1004,21 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.IdentityRef != nil { + if in.ServerGroup != nil { + in, out := &in.ServerGroup, &out.ServerGroup + *out = new(ServerGroupParam) + (*in).DeepCopyInto(*out) + } + if in.IdentityRef != nil { in, out := &in.IdentityRef, &out.IdentityRef *out = new(OpenStackIdentityReference) **out = **in } + if in.FloatingIPPoolRef != nil { + in, out := &in.FloatingIPPoolRef, &out.FloatingIPPoolRef + *out = new(v1.TypedLocalObjectReference) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineSpec. @@ -706,6 +1034,11 @@ func (in *OpenStackMachineSpec) DeepCopy() *OpenStackMachineSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) { *out = *in + if in.InstanceID != nil { + in, out := &in.InstanceID, &out.InstanceID + *out = new(string) + **out = **in + } if in.Addresses != nil { in, out := &in.Addresses, &out.Addresses *out = make([]v1.NodeAddress, len(*in)) @@ -716,6 +1049,16 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) { *out = new(InstanceState) **out = **in } + if in.Resolved != nil { + in, out := &in.Resolved, &out.Resolved + *out = new(ResolvedMachineSpec) + (*in).DeepCopyInto(*out) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(MachineResources) + (*in).DeepCopyInto(*out) + } if in.FailureReason != nil { in, out := &in.FailureReason, &out.FailureReason *out = new(errors.MachineStatusError) @@ -728,7 +1071,7 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) { } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make(v1beta1.Conditions, len(*in)) + *out = make(apiv1beta1.Conditions, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -840,12 +1183,17 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) { *out = *in if in.Network != nil { in, out := &in.Network, &out.Network - *out = new(NetworkFilter) + *out = new(NetworkParam) + (*in).DeepCopyInto(*out) + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) **out = **in } - if in.AdminStateUp != nil { - in, out := &in.AdminStateUp, &out.AdminStateUp - *out = new(bool) + if in.NameSuffix != nil { + in, out := &in.NameSuffix, &out.NameSuffix + *out = new(string) **out = **in } if in.FixedIPs != nil { @@ -855,14 +1203,104 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.SecurityGroupFilters != nil { - in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters - *out = make([]SecurityGroupFilter, len(*in)) + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]SecurityGroupParam, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) copy(*out, *in) } - if in.AllowedAddressPairs != nil { - in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs - *out = make([]AddressPair, len(*in)) + if in.Trunk != nil { + in, out := &in.Trunk, &out.Trunk + *out = new(bool) + **out = **in + } + in.ResolvedPortSpecFields.DeepCopyInto(&out.ResolvedPortSpecFields) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortOpts. +func (in *PortOpts) DeepCopy() *PortOpts { + if in == nil { + return nil + } + out := new(PortOpts) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PortStatus) DeepCopyInto(out *PortStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortStatus. +func (in *PortStatus) DeepCopy() *PortStatus { + if in == nil { + return nil + } + out := new(PortStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolvedFixedIP) DeepCopyInto(out *ResolvedFixedIP) { + *out = *in + if in.SubnetID != nil { + in, out := &in.SubnetID, &out.SubnetID + *out = new(string) + **out = **in + } + if in.IPAddress != nil { + in, out := &in.IPAddress, &out.IPAddress + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolvedFixedIP. +func (in *ResolvedFixedIP) DeepCopy() *ResolvedFixedIP { + if in == nil { + return nil + } + out := new(ResolvedFixedIP) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolvedMachineSpec) DeepCopyInto(out *ResolvedMachineSpec) { + *out = *in + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]ResolvedPortSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolvedMachineSpec. +func (in *ResolvedMachineSpec) DeepCopy() *ResolvedMachineSpec { + if in == nil { + return nil + } + out := new(ResolvedMachineSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolvedPortSpec) DeepCopyInto(out *ResolvedPortSpec) { + *out = *in + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) copy(*out, *in) } if in.Trunk != nil { @@ -870,7 +1308,66 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) { *out = new(bool) **out = **in } - out.Profile = in.Profile + if in.FixedIPs != nil { + in, out := &in.FixedIPs, &out.FixedIPs + *out = make([]ResolvedFixedIP, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + in.ResolvedPortSpecFields.DeepCopyInto(&out.ResolvedPortSpecFields) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolvedPortSpec. +func (in *ResolvedPortSpec) DeepCopy() *ResolvedPortSpec { + if in == nil { + return nil + } + out := new(ResolvedPortSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolvedPortSpecFields) DeepCopyInto(out *ResolvedPortSpecFields) { + *out = *in + if in.AdminStateUp != nil { + in, out := &in.AdminStateUp, &out.AdminStateUp + *out = new(bool) + **out = **in + } + if in.MACAddress != nil { + in, out := &in.MACAddress, &out.MACAddress + *out = new(string) + **out = **in + } + if in.AllowedAddressPairs != nil { + in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs + *out = make([]AddressPair, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.HostID != nil { + in, out := &in.HostID, &out.HostID + *out = new(string) + **out = **in + } + if in.VNICType != nil { + in, out := &in.VNICType, &out.VNICType + *out = new(string) + **out = **in + } + if in.Profile != nil { + in, out := &in.Profile, &out.Profile + *out = new(BindingProfile) + (*in).DeepCopyInto(*out) + } if in.DisablePortSecurity != nil { in, out := &in.DisablePortSecurity, &out.DisablePortSecurity *out = new(bool) @@ -881,11 +1378,6 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) { *out = new(bool) **out = **in } - if in.Tags != nil { - in, out := &in.Tags, &out.Tags - *out = make([]string, len(*in)) - copy(*out, *in) - } if in.ValueSpecs != nil { in, out := &in.ValueSpecs, &out.ValueSpecs *out = make([]ValueSpec, len(*in)) @@ -893,12 +1385,12 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortOpts. -func (in *PortOpts) DeepCopy() *PortOpts { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolvedPortSpecFields. +func (in *ResolvedPortSpecFields) DeepCopy() *ResolvedPortSpecFields { if in == nil { return nil } - out := new(PortOpts) + out := new(ResolvedPortSpecFields) in.DeepCopyInto(out) return out } @@ -906,6 +1398,7 @@ func (in *PortOpts) DeepCopy() *PortOpts { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RootVolume) DeepCopyInto(out *RootVolume) { *out = *in + in.BlockDeviceVolume.DeepCopyInto(&out.BlockDeviceVolume) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RootVolume. @@ -946,6 +1439,7 @@ func (in *Router) DeepCopy() *Router { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouterFilter) DeepCopyInto(out *RouterFilter) { *out = *in + in.FilterByNeutronTags.DeepCopyInto(&out.FilterByNeutronTags) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterFilter. @@ -959,21 +1453,26 @@ func (in *RouterFilter) DeepCopy() *RouterFilter { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityGroup) DeepCopyInto(out *SecurityGroup) { +func (in *RouterParam) DeepCopyInto(out *RouterParam) { *out = *in - if in.Rules != nil { - in, out := &in.Rules, &out.Rules - *out = make([]SecurityGroupRule, len(*in)) - copy(*out, *in) + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(RouterFilter) + (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroup. -func (in *SecurityGroup) DeepCopy() *SecurityGroup { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterParam. +func (in *RouterParam) DeepCopy() *RouterParam { if in == nil { return nil } - out := new(SecurityGroup) + out := new(RouterParam) in.DeepCopyInto(out) return out } @@ -981,6 +1480,7 @@ func (in *SecurityGroup) DeepCopy() *SecurityGroup { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityGroupFilter) DeepCopyInto(out *SecurityGroupFilter) { *out = *in + in.FilterByNeutronTags.DeepCopyInto(&out.FilterByNeutronTags) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupFilter. @@ -994,16 +1494,156 @@ func (in *SecurityGroupFilter) DeepCopy() *SecurityGroupFilter { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityGroupRule) DeepCopyInto(out *SecurityGroupRule) { +func (in *SecurityGroupParam) DeepCopyInto(out *SecurityGroupParam) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(SecurityGroupFilter) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupParam. +func (in *SecurityGroupParam) DeepCopy() *SecurityGroupParam { + if in == nil { + return nil + } + out := new(SecurityGroupParam) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityGroupRuleSpec) DeepCopyInto(out *SecurityGroupRuleSpec) { + *out = *in + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.EtherType != nil { + in, out := &in.EtherType, &out.EtherType + *out = new(string) + **out = **in + } + if in.PortRangeMin != nil { + in, out := &in.PortRangeMin, &out.PortRangeMin + *out = new(int) + **out = **in + } + if in.PortRangeMax != nil { + in, out := &in.PortRangeMax, &out.PortRangeMax + *out = new(int) + **out = **in + } + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(string) + **out = **in + } + if in.RemoteGroupID != nil { + in, out := &in.RemoteGroupID, &out.RemoteGroupID + *out = new(string) + **out = **in + } + if in.RemoteIPPrefix != nil { + in, out := &in.RemoteIPPrefix, &out.RemoteIPPrefix + *out = new(string) + **out = **in + } + if in.RemoteManagedGroups != nil { + in, out := &in.RemoteManagedGroups, &out.RemoteManagedGroups + *out = make([]ManagedSecurityGroupName, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupRuleSpec. +func (in *SecurityGroupRuleSpec) DeepCopy() *SecurityGroupRuleSpec { + if in == nil { + return nil + } + out := new(SecurityGroupRuleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityGroupStatus) DeepCopyInto(out *SecurityGroupStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupStatus. +func (in *SecurityGroupStatus) DeepCopy() *SecurityGroupStatus { + if in == nil { + return nil + } + out := new(SecurityGroupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerGroupFilter) DeepCopyInto(out *ServerGroupFilter) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupFilter. +func (in *ServerGroupFilter) DeepCopy() *ServerGroupFilter { + if in == nil { + return nil + } + out := new(ServerGroupFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerGroupParam) DeepCopyInto(out *ServerGroupParam) { *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(ServerGroupFilter) + (*in).DeepCopyInto(*out) + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupRule. -func (in *SecurityGroupRule) DeepCopy() *SecurityGroupRule { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupParam. +func (in *ServerGroupParam) DeepCopy() *ServerGroupParam { if in == nil { return nil } - out := new(SecurityGroupRule) + out := new(ServerGroupParam) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerMetadata) DeepCopyInto(out *ServerMetadata) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerMetadata. +func (in *ServerMetadata) DeepCopy() *ServerMetadata { + if in == nil { + return nil + } + out := new(ServerMetadata) in.DeepCopyInto(out) return out } @@ -1031,6 +1671,7 @@ func (in *Subnet) DeepCopy() *Subnet { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubnetFilter) DeepCopyInto(out *SubnetFilter) { *out = *in + in.FilterByNeutronTags.DeepCopyInto(&out.FilterByNeutronTags) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetFilter. @@ -1043,6 +1684,56 @@ func (in *SubnetFilter) DeepCopy() *SubnetFilter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubnetParam) DeepCopyInto(out *SubnetParam) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(SubnetFilter) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetParam. +func (in *SubnetParam) DeepCopy() *SubnetParam { + if in == nil { + return nil + } + out := new(SubnetParam) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubnetSpec) DeepCopyInto(out *SubnetSpec) { + *out = *in + if in.DNSNameservers != nil { + in, out := &in.DNSNameservers, &out.DNSNameservers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AllocationPools != nil { + in, out := &in.AllocationPools, &out.AllocationPools + *out = make([]AllocationPool, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetSpec. +func (in *SubnetSpec) DeepCopy() *SubnetSpec { + if in == nil { + return nil + } + out := new(SubnetSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ValueSpec) DeepCopyInto(out *ValueSpec) { *out = *in @@ -1057,3 +1748,23 @@ func (in *ValueSpec) DeepCopy() *ValueSpec { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeAvailabilityZone) DeepCopyInto(out *VolumeAvailabilityZone) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(VolumeAZName) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeAvailabilityZone. +func (in *VolumeAvailabilityZone) DeepCopy() *VolumeAvailabilityZone { + if in == nil { + return nil + } + out := new(VolumeAvailabilityZone) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml index a5114ac6a2..fd240c51f5 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: openstackclusters.infrastructure.cluster.x-k8s.io spec: group: infrastructure.cluster.x-k8s.io @@ -54,18 +54,26 @@ spec: name: v1alpha5 schema: openAPIV3Schema: - description: "OpenStackCluster is the Schema for the openstackclusters API. - \n Deprecated: This type will be removed in one of the next releases." + description: |- + OpenStackCluster is the Schema for the openstackclusters API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -73,31 +81,34 @@ spec: description: OpenStackClusterSpec defines the desired state of OpenStackCluster. properties: allowAllInClusterTraffic: - description: AllowAllInClusterTraffic is only used when managed security - groups are in use. If set to true, the rules for the managed security - groups are configured so that all ingress and egress between cluster - nodes is permitted, allowing CNIs other than Calico to be used. + description: |- + AllowAllInClusterTraffic is only used when managed security groups are in use. + If set to true, the rules for the managed security groups are configured so that all + ingress and egress between cluster nodes is permitted, allowing CNIs other than + Calico to be used. type: boolean apiServerFixedIP: - description: APIServerFixedIP is the fixed IP which will be associated - with the API server. In the case where the API server has a floating - IP but not a managed load balancer, this field is not used. If a - managed load balancer is used and this field is not specified, a - fixed IP will be dynamically allocated for the load balancer. If - a managed load balancer is not used AND the API server floating - IP is disabled, this field MUST be specified and should correspond - to a pre-allocated port that holds the fixed IP to be used as a - VIP. + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. type: string apiServerFloatingIP: - description: APIServerFloatingIP is the floatingIP which will be associated - with the API server. The floatingIP will be created if it does not - already exist. If not specified, a new floatingIP is allocated. + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. This field is not used if DisableAPIServerFloatingIP is set to true. type: string apiServerLoadBalancer: - description: 'APIServerLoadBalancer configures the optional LoadBalancer - for the APIServer. It must be activated by setting `enabled: true`.' + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + It must be activated by setting `enabled: true`. properties: additionalPorts: description: AdditionalPorts adds additional tcp ports to the @@ -117,14 +128,18 @@ spec: type: boolean type: object apiServerPort: - description: APIServerPort is the port on which the listener on the - APIServer will be created + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created type: integer bastion: - description: "Bastion is the OpenStack instance to login the nodes - \n As a rolling update is not ideal during a bastion host session, - we prevent changes to a running bastion configuration. Set `enabled: - false` to make changes." + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. Set `enabled: false` to + make changes. properties: availabilityZone: type: string @@ -145,48 +160,48 @@ spec: server instance. type: string floatingIP: - description: The floatingIP which will be associated to the - machine, only used for master. The floatingIP should have - been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server - instance. If the RootVolume is specified, this will be ignored - and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server - instance. if it's empty, Image name will be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter when there - are multiple networks defined for the tenant. When you do - not specify both networks and ports parameters, the server - attaches to the only network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -247,26 +262,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must - also be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If specified - this will not be validated prior to server creation. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does not - already exist. When you do not specify both networks and - ports parameters, the server attaches to the only network - created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -283,10 +297,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -297,10 +310,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -344,9 +356,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -368,10 +380,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and receive - virtual network interface (VIF) port-specific information - to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -426,10 +438,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -520,7 +531,9 @@ spec: be marked as AccessIPv4 on the created compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -557,40 +570,42 @@ spec: - port type: object disableAPIServerFloatingIP: - description: DisableAPIServerFloatingIP determines whether or not - to attempt to attach a floating IP to the API server. This allows - for the creation of clusters when attaching a floating IP to the - API server (and hence, in many cases, exposing the API server to - the internet) is not possible or desirable, e.g. if using a shared - VLAN for communication between management and workload clusters - or when the management cluster is inside the project network. This - option requires that the API server use a VIP on the cluster network - so that the underlying machines can change without changing ControlPlaneEndpoint.Host. + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. When using a managed load balancer, this VIP will be managed automatically. - If not using a managed load balancer, cluster configuration will - fail without additional configuration to manage the VIP on the control - plane machines, which falls outside of the scope of this controller. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. type: boolean disablePortSecurity: - description: DisablePortSecurity disables the port security of the - network created for the Kubernetes cluster, which also disables - SecurityGroups + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups type: boolean dnsNameservers: - description: DNSNameservers is the list of nameservers for OpenStack - Subnet being created. Set this value when you need create a new - network/subnet while the access through DNS is required. + description: |- + DNSNameservers is the list of nameservers for OpenStack Subnet being created. + Set this value when you need create a new network/subnet while the access + through DNS is required. items: type: string type: array externalNetworkId: - description: ExternalNetworkID is the ID of an external OpenStack - Network. This is necessary to get public internet to the VMs. + description: |- + ExternalNetworkID is the ID of an external OpenStack Network. This is necessary + to get public internet to the VMs. type: string externalRouterIPs: - description: ExternalRouterIPs is an array of externalIPs on the respective - subnets. This is necessary if the router needs a fixed ip in a specific - subnet. + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. items: properties: fixedIP: @@ -631,10 +646,10 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified this - will not be validated prior to server creation. If specified, - the enclosing `NetworkParam` must also be specified by - UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object required: @@ -646,26 +661,28 @@ spec: reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by the infrastructure + description: |- + Kind of the identity. Must be supported by the infrastructure provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be used. Must - be either a cluster-scoped resource, or namespaced-scoped resource - the same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object managedSecurityGroups: - description: ManagedSecurityGroups determines whether OpenStack security - groups for the cluster will be managed by the OpenStack provider - or whether pre-existing security groups will be specified as part - of the configuration. By default, the managed security groups have - rules that allow the Kubelet, etcd, the Kubernetes API server and - the Calico CNI plugin to function correctly. + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, the + Kubernetes API server and the Calico CNI plugin to function correctly. type: boolean network: description: If NodeCIDR cannot be set this can be used to detect @@ -689,10 +706,10 @@ spec: type: string type: object nodeCidr: - description: NodeCIDR is the OpenStack Subnet to be created. Cluster - actuator will create a network, a subnet with NodeCIDR, and a router - connected to this subnet. If you leave this empty, no network will - be created. + description: |- + NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a + network, a subnet with NodeCIDR, and a router connected to this subnet. + If you leave this empty, no network will be created. type: string subnet: description: If NodeCIDR cannot be set this can be used to detect @@ -764,9 +781,9 @@ spec: Neutron Network associated with an instance's port. properties: apiServerLoadBalancer: - description: Be careful when using APIServerLoadBalancer, - because this field is optional and therefore not set in - all cases + description: |- + Be careful when using APIServerLoadBalancer, because this field is optional and therefore not + set in all cases properties: allowedCIDRs: items: @@ -806,10 +823,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -820,10 +836,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -867,9 +882,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -891,10 +906,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and receive - virtual network interface (VIF) port-specific information - to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -949,10 +964,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1048,8 +1062,9 @@ spec: type: string type: object bastionSecurityGroup: - description: SecurityGroup represents the basic information of the - associated OpenStack Neutron Security Group. + description: |- + SecurityGroup represents the basic information of the associated + OpenStack Neutron Security Group. properties: id: type: string @@ -1057,8 +1072,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -1096,13 +1112,12 @@ spec: required: - id - name - - rules type: object controlPlaneSecurityGroup: - description: 'ControlPlaneSecurityGroups contains all the information - about the OpenStack Security Group that needs to be applied to control - plane nodes. TODO: Maybe instead of two properties, we add a property - to the group?' + description: |- + ControlPlaneSecurityGroups contains all the information about the OpenStack + Security Group that needs to be applied to control plane nodes. + TODO: Maybe instead of two properties, we add a property to the group? properties: id: type: string @@ -1110,8 +1125,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -1149,15 +1165,15 @@ spec: required: - id - name - - rules type: object externalNetwork: description: External Network contains information about the created OpenStack external network. properties: apiServerLoadBalancer: - description: Be careful when using APIServerLoadBalancer, because - this field is optional and therefore not set in all cases + description: |- + Be careful when using APIServerLoadBalancer, because this field is optional and therefore not + set in all cases properties: allowedCIDRs: items: @@ -1197,9 +1213,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -1209,10 +1225,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed - IP of a port in. This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -1256,9 +1271,9 @@ spec: list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -1280,9 +1295,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application running - on the specified host to pass and receive virtual network - interface (VIF) port-specific information to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -1337,10 +1353,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1404,9 +1419,9 @@ spec: type: object failureDomains: additionalProperties: - description: FailureDomainSpec is the Schema for Cluster API failure - domains. It allows controllers to understand how many failure - domains a cluster can optionally span across. + description: |- + FailureDomainSpec is the Schema for Cluster API failure domains. + It allows controllers to understand how many failure domains a cluster can optionally span across. properties: attributes: additionalProperties: @@ -1422,44 +1437,56 @@ spec: description: FailureDomains represent OpenStack availability zones type: object failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the OpenStackCluster and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the OpenStackCluster's spec or the configuration of the - controller, and that manual intervention is required. Examples of - terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the responsible - controller itself being critically misconfigured. \n Any transient - errors that occur during the reconciliation of OpenStackClusters - can be added as events to the OpenStackCluster object and/or logged - in the controller's output." + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. type: string failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the OpenStackCluster and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the OpenStackCluster's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of OpenStackClusters can be added - as events to the OpenStackCluster object and/or logged in the controller's - output." + description: |- + FailureReason will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a succinct value suitable + for machine interpretation. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. type: string network: - description: Network contains all information about the created OpenStack - Network. It includes Subnets and Router. + description: |- + Network contains all information about the created OpenStack Network. + It includes Subnets and Router. properties: apiServerLoadBalancer: - description: Be careful when using APIServerLoadBalancer, because - this field is optional and therefore not set in all cases + description: |- + Be careful when using APIServerLoadBalancer, because this field is optional and therefore not + set in all cases properties: allowedCIDRs: items: @@ -1499,9 +1526,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -1511,10 +1538,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed - IP of a port in. This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -1558,9 +1584,9 @@ spec: list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -1582,9 +1608,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application running - on the specified host to pass and receive virtual network - interface (VIF) port-specific information to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -1639,10 +1666,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1707,9 +1733,9 @@ spec: ready: type: boolean workerSecurityGroup: - description: WorkerSecurityGroup contains all the information about - the OpenStack Security Group that needs to be applied to worker - nodes. + description: |- + WorkerSecurityGroup contains all the information about the OpenStack Security + Group that needs to be applied to worker nodes. properties: id: type: string @@ -1717,8 +1743,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -1756,13 +1783,12 @@ spec: required: - id - name - - rules type: object required: - ready type: object type: object - served: true + served: false storage: false subresources: status: {} @@ -1796,20 +1822,32 @@ spec: jsonPath: .metadata.creationTimestamp name: Age type: date + deprecated: true + deprecationWarning: The v1alpha6 version of OpenStackCluster has been deprecated + and will be removed in a future release of the API. Please upgrade. name: v1alpha6 schema: openAPIV3Schema: - description: OpenStackCluster is the Schema for the openstackclusters API. + description: |- + OpenStackCluster is the Schema for the openstackclusters API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -1817,31 +1855,34 @@ spec: description: OpenStackClusterSpec defines the desired state of OpenStackCluster. properties: allowAllInClusterTraffic: - description: AllowAllInClusterTraffic is only used when managed security - groups are in use. If set to true, the rules for the managed security - groups are configured so that all ingress and egress between cluster - nodes is permitted, allowing CNIs other than Calico to be used. + description: |- + AllowAllInClusterTraffic is only used when managed security groups are in use. + If set to true, the rules for the managed security groups are configured so that all + ingress and egress between cluster nodes is permitted, allowing CNIs other than + Calico to be used. type: boolean apiServerFixedIP: - description: APIServerFixedIP is the fixed IP which will be associated - with the API server. In the case where the API server has a floating - IP but not a managed load balancer, this field is not used. If a - managed load balancer is used and this field is not specified, a - fixed IP will be dynamically allocated for the load balancer. If - a managed load balancer is not used AND the API server floating - IP is disabled, this field MUST be specified and should correspond - to a pre-allocated port that holds the fixed IP to be used as a - VIP. + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. type: string apiServerFloatingIP: - description: APIServerFloatingIP is the floatingIP which will be associated - with the API server. The floatingIP will be created if it does not - already exist. If not specified, a new floatingIP is allocated. + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. This field is not used if DisableAPIServerFloatingIP is set to true. type: string apiServerLoadBalancer: - description: 'APIServerLoadBalancer configures the optional LoadBalancer - for the APIServer. It must be activated by setting `enabled: true`.' + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + It must be activated by setting `enabled: true`. properties: additionalPorts: description: AdditionalPorts adds additional tcp ports to the @@ -1864,14 +1905,18 @@ spec: type: string type: object apiServerPort: - description: APIServerPort is the port on which the listener on the - APIServer will be created + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created type: integer bastion: - description: "Bastion is the OpenStack instance to login the nodes - \n As a rolling update is not ideal during a bastion host session, - we prevent changes to a running bastion configuration. Set `enabled: - false` to make changes." + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. Set `enabled: false` to + make changes. properties: availabilityZone: type: string @@ -1892,48 +1937,48 @@ spec: server instance. type: string floatingIP: - description: The floatingIP which will be associated to the - machine, only used for master. The floatingIP should have - been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server - instance. If the RootVolume is specified, this will be ignored - and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server - instance. if it's empty, Image name will be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter when there - are multiple networks defined for the tenant. When you do - not specify both networks and ports parameters, the server - attaches to the only network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -1994,26 +2039,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must - also be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If specified - this will not be validated prior to server creation. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does not - already exist. When you do not specify both networks and - ports parameters, the server attaches to the only network - created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -2030,10 +2074,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -2044,10 +2087,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -2091,9 +2133,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -2115,10 +2157,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and receive - virtual network interface (VIF) port-specific information - to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -2174,10 +2216,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -2189,10 +2230,10 @@ spec: If not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include - in the API request with OpenStack. This is an extension - point for the API, so what they do and if they are - supported, depends on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -2201,9 +2242,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the pair - and will not be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value @@ -2299,7 +2340,9 @@ spec: be marked as AccessIPv4 on the created compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -2338,46 +2381,48 @@ spec: - port type: object controlPlaneOmitAvailabilityZone: - description: Indicates whether to omit the az for control plane nodes, - allowing the Nova scheduler to make a decision on which az to use - based on other scheduling constraints + description: |- + Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler + to make a decision on which az to use based on other scheduling constraints type: boolean disableAPIServerFloatingIP: - description: DisableAPIServerFloatingIP determines whether or not - to attempt to attach a floating IP to the API server. This allows - for the creation of clusters when attaching a floating IP to the - API server (and hence, in many cases, exposing the API server to - the internet) is not possible or desirable, e.g. if using a shared - VLAN for communication between management and workload clusters - or when the management cluster is inside the project network. This - option requires that the API server use a VIP on the cluster network - so that the underlying machines can change without changing ControlPlaneEndpoint.Host. + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. When using a managed load balancer, this VIP will be managed automatically. - If not using a managed load balancer, cluster configuration will - fail without additional configuration to manage the VIP on the control - plane machines, which falls outside of the scope of this controller. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. type: boolean disablePortSecurity: - description: DisablePortSecurity disables the port security of the - network created for the Kubernetes cluster, which also disables - SecurityGroups + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups type: boolean dnsNameservers: - description: DNSNameservers is the list of nameservers for OpenStack - Subnet being created. Set this value when you need create a new - network/subnet while the access through DNS is required. + description: |- + DNSNameservers is the list of nameservers for OpenStack Subnet being created. + Set this value when you need create a new network/subnet while the access + through DNS is required. items: type: string type: array x-kubernetes-list-type: set externalNetworkId: - description: ExternalNetworkID is the ID of an external OpenStack - Network. This is necessary to get public internet to the VMs. + description: |- + ExternalNetworkID is the ID of an external OpenStack Network. This is necessary + to get public internet to the VMs. type: string externalRouterIPs: - description: ExternalRouterIPs is an array of externalIPs on the respective - subnets. This is necessary if the router needs a fixed ip in a specific - subnet. + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. items: properties: fixedIP: @@ -2418,10 +2463,10 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified this - will not be validated prior to server creation. If specified, - the enclosing `NetworkParam` must also be specified by - UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object required: @@ -2433,26 +2478,28 @@ spec: reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by the infrastructure + description: |- + Kind of the identity. Must be supported by the infrastructure provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be used. Must - be either a cluster-scoped resource, or namespaced-scoped resource - the same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object managedSecurityGroups: - description: ManagedSecurityGroups determines whether OpenStack security - groups for the cluster will be managed by the OpenStack provider - or whether pre-existing security groups will be specified as part - of the configuration. By default, the managed security groups have - rules that allow the Kubelet, etcd, the Kubernetes API server and - the Calico CNI plugin to function correctly. + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, the + Kubernetes API server and the Calico CNI plugin to function correctly. type: boolean network: description: If NodeCIDR cannot be set this can be used to detect @@ -2476,10 +2523,10 @@ spec: type: string type: object nodeCidr: - description: NodeCIDR is the OpenStack Subnet to be created. Cluster - actuator will create a network, a subnet with NodeCIDR, and a router - connected to this subnet. If you leave this empty, no network will - be created. + description: |- + NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a + network, a subnet with NodeCIDR, and a router connected to this subnet. + If you leave this empty, no network will be created. type: string subnet: description: If NodeCIDR cannot be set this can be used to detect @@ -2552,9 +2599,9 @@ spec: Neutron Network associated with an instance's port. properties: apiServerLoadBalancer: - description: Be careful when using APIServerLoadBalancer, - because this field is optional and therefore not set in - all cases + description: |- + Be careful when using APIServerLoadBalancer, because this field is optional and therefore not + set in all cases properties: allowedCIDRs: items: @@ -2598,10 +2645,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -2612,10 +2658,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -2659,9 +2704,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -2683,10 +2728,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and receive - virtual network interface (VIF) port-specific information - to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -2742,10 +2787,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -2757,10 +2801,10 @@ spec: If not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include - in the API request with OpenStack. This is an extension - point for the API, so what they do and if they are - supported, depends on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -2769,9 +2813,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the pair - and will not be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value @@ -2872,8 +2916,9 @@ spec: type: string type: object bastionSecurityGroup: - description: SecurityGroup represents the basic information of the - associated OpenStack Neutron Security Group. + description: |- + SecurityGroup represents the basic information of the associated + OpenStack Neutron Security Group. properties: id: type: string @@ -2881,8 +2926,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -2920,13 +2966,12 @@ spec: required: - id - name - - rules type: object controlPlaneSecurityGroup: - description: 'ControlPlaneSecurityGroups contains all the information - about the OpenStack Security Group that needs to be applied to control - plane nodes. TODO: Maybe instead of two properties, we add a property - to the group?' + description: |- + ControlPlaneSecurityGroups contains all the information about the OpenStack + Security Group that needs to be applied to control plane nodes. + TODO: Maybe instead of two properties, we add a property to the group? properties: id: type: string @@ -2934,8 +2979,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -2973,15 +3019,15 @@ spec: required: - id - name - - rules type: object externalNetwork: description: External Network contains information about the created OpenStack external network. properties: apiServerLoadBalancer: - description: Be careful when using APIServerLoadBalancer, because - this field is optional and therefore not set in all cases + description: |- + Be careful when using APIServerLoadBalancer, because this field is optional and therefore not + set in all cases properties: allowedCIDRs: items: @@ -3025,9 +3071,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -3037,10 +3083,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed - IP of a port in. This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -3084,9 +3129,9 @@ spec: list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -3108,9 +3153,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application running - on the specified host to pass and receive virtual network - interface (VIF) port-specific information to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -3166,10 +3212,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -3181,9 +3226,9 @@ spec: not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include in - the API request with OpenStack. This is an extension point - for the API, so what they do and if they are supported, + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value @@ -3193,9 +3238,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value pair. - This is just for identifying the pair and will not - be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value pair. @@ -3263,9 +3308,9 @@ spec: type: object failureDomains: additionalProperties: - description: FailureDomainSpec is the Schema for Cluster API failure - domains. It allows controllers to understand how many failure - domains a cluster can optionally span across. + description: |- + FailureDomainSpec is the Schema for Cluster API failure domains. + It allows controllers to understand how many failure domains a cluster can optionally span across. properties: attributes: additionalProperties: @@ -3281,44 +3326,56 @@ spec: description: FailureDomains represent OpenStack availability zones type: object failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the OpenStackCluster and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the OpenStackCluster's spec or the configuration of the - controller, and that manual intervention is required. Examples of - terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the responsible - controller itself being critically misconfigured. \n Any transient - errors that occur during the reconciliation of OpenStackClusters - can be added as events to the OpenStackCluster object and/or logged - in the controller's output." + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. type: string failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the OpenStackCluster and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the OpenStackCluster's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of OpenStackClusters can be added - as events to the OpenStackCluster object and/or logged in the controller's - output." + description: |- + FailureReason will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a succinct value suitable + for machine interpretation. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. type: string network: - description: Network contains all information about the created OpenStack - Network. It includes Subnets and Router. + description: |- + Network contains all information about the created OpenStack Network. + It includes Subnets and Router. properties: apiServerLoadBalancer: - description: Be careful when using APIServerLoadBalancer, because - this field is optional and therefore not set in all cases + description: |- + Be careful when using APIServerLoadBalancer, because this field is optional and therefore not + set in all cases properties: allowedCIDRs: items: @@ -3362,9 +3419,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -3374,10 +3431,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed - IP of a port in. This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -3421,9 +3477,9 @@ spec: list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -3445,9 +3501,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application running - on the specified host to pass and receive virtual network - interface (VIF) port-specific information to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -3503,10 +3560,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -3518,9 +3574,9 @@ spec: not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include in - the API request with OpenStack. This is an extension point - for the API, so what they do and if they are supported, + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value @@ -3530,9 +3586,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value pair. - This is just for identifying the pair and will not - be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value pair. @@ -3601,9 +3657,9 @@ spec: ready: type: boolean workerSecurityGroup: - description: WorkerSecurityGroup contains all the information about - the OpenStack Security Group that needs to be applied to worker - nodes. + description: |- + WorkerSecurityGroup contains all the information about the OpenStack Security + Group that needs to be applied to worker nodes. properties: id: type: string @@ -3611,8 +3667,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -3650,7 +3707,6 @@ spec: required: - id - name - - rules type: object required: - ready @@ -3692,14 +3748,19 @@ spec: description: OpenStackCluster is the Schema for the openstackclusters API. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -3707,31 +3768,34 @@ spec: description: OpenStackClusterSpec defines the desired state of OpenStackCluster. properties: allowAllInClusterTraffic: - description: AllowAllInClusterTraffic is only used when managed security - groups are in use. If set to true, the rules for the managed security - groups are configured so that all ingress and egress between cluster - nodes is permitted, allowing CNIs other than Calico to be used. + description: |- + AllowAllInClusterTraffic is only used when managed security groups are in use. + If set to true, the rules for the managed security groups are configured so that all + ingress and egress between cluster nodes is permitted, allowing CNIs other than + Calico to be used. type: boolean apiServerFixedIP: - description: APIServerFixedIP is the fixed IP which will be associated - with the API server. In the case where the API server has a floating - IP but not a managed load balancer, this field is not used. If a - managed load balancer is used and this field is not specified, a - fixed IP will be dynamically allocated for the load balancer. If - a managed load balancer is not used AND the API server floating - IP is disabled, this field MUST be specified and should correspond - to a pre-allocated port that holds the fixed IP to be used as a - VIP. + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. type: string apiServerFloatingIP: - description: APIServerFloatingIP is the floatingIP which will be associated - with the API server. The floatingIP will be created if it does not - already exist. If not specified, a new floatingIP is allocated. + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. This field is not used if DisableAPIServerFloatingIP is set to true. type: string apiServerLoadBalancer: - description: 'APIServerLoadBalancer configures the optional LoadBalancer - for the APIServer. It must be activated by setting `enabled: true`.' + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + It must be activated by setting `enabled: true`. properties: additionalPorts: description: AdditionalPorts adds additional tcp ports to the @@ -3754,14 +3818,18 @@ spec: type: string type: object apiServerPort: - description: APIServerPort is the port on which the listener on the - APIServer will be created + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created type: integer bastion: - description: "Bastion is the OpenStack instance to login the nodes - \n As a rolling update is not ideal during a bastion host session, - we prevent changes to a running bastion configuration. Set `enabled: - false` to make changes." + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. Set `enabled: false` to + make changes. properties: availabilityZone: type: string @@ -3778,12 +3846,12 @@ spec: attach to the server. properties: name: - description: Name of the block device in the context - of a machine. If the block device is a volume, the - Cinder volume will be named as a combination of the - machine name and this name. Also, this name will be - used for tagging the block device. Information about - the block device tag can be obtained from the OpenStack + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack metadata API or the config drive. type: string sizeGiB: @@ -3791,32 +3859,32 @@ spec: in gibibytes (GiB). type: integer storage: - description: Storage specifies the storage type of the - block device and additional storage options. + description: |- + Storage specifies the storage type of the block device and + additional storage options. properties: type: - description: Type is the type of block device to - create. This can be either "Volume" or "Local". + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". type: string volume: description: Volume contains additional storage options for a volume block device. properties: availabilityZone: - description: AvailabilityZone is the volume - availability zone to create the volume in. - If omitted, the availability zone of the server - will be used. The availability zone must NOT - contain spaces otherwise it will lead to volume - that belongs to this availability zone register - failure, see kubernetes/cloud-provider-openstack#1379 - for further information. + description: |- + AvailabilityZone is the volume availability zone to create the volume in. + If omitted, the availability zone of the server will be used. + The availability zone must NOT contain spaces otherwise it will lead to volume that belongs + to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for + further information. type: string type: - description: Type is the Cinder volume type - of the volume. If omitted, the default Cinder - volume type that is configured in the OpenStack - cloud will be used. + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. type: string type: object required: @@ -3843,48 +3911,49 @@ spec: server instance. type: string floatingIP: - description: The floatingIP which will be associated to the - machine, only used for master. The floatingIP should have - been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: - description: IdentityRef is a reference to a identity to be - used when reconciling this cluster + description: |- + IdentityRef is a reference to a identity to be used when reconciling this cluster. + If not specified, the identity ref of the cluster will be used instead. properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server - instance. If the RootVolume is specified, this will be ignored - and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server - instance. if it's empty, Image name will be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does not - already exist. If not specified a default port will be added - for the default cluster network. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. items: properties: adminStateUp: @@ -3901,10 +3970,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -3915,10 +3983,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -3962,9 +4029,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -3984,12 +4051,11 @@ spec: type: string type: object profile: - description: Profile is a set of key-value pairs that - are used for binding details. We intentionally don't - expose this as a map[string]string because we only - want to enable the users to set the values of the - keys that are known to work in OpenStack Networking - API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + description: |- + Profile is a set of key-value pairs that are used for binding details. + We intentionally don't expose this as a map[string]string because we only want to enable + the users to set the values of the keys that are known to work in OpenStack Networking API. + See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port properties: ovsHWOffload: description: OVSHWOffload enables or disables the @@ -4028,10 +4094,9 @@ spec: type: object type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -4041,10 +4106,10 @@ spec: If not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include - in the API request with OpenStack. This is an extension - point for the API, so what they do and if they are - supported, depends on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -4053,9 +4118,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the pair - and will not be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value @@ -4126,7 +4191,9 @@ spec: description: The ssh key to inject in the instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -4165,46 +4232,48 @@ spec: - port type: object controlPlaneOmitAvailabilityZone: - description: Indicates whether to omit the az for control plane nodes, - allowing the Nova scheduler to make a decision on which az to use - based on other scheduling constraints + description: |- + Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler + to make a decision on which az to use based on other scheduling constraints type: boolean disableAPIServerFloatingIP: - description: DisableAPIServerFloatingIP determines whether or not - to attempt to attach a floating IP to the API server. This allows - for the creation of clusters when attaching a floating IP to the - API server (and hence, in many cases, exposing the API server to - the internet) is not possible or desirable, e.g. if using a shared - VLAN for communication between management and workload clusters - or when the management cluster is inside the project network. This - option requires that the API server use a VIP on the cluster network - so that the underlying machines can change without changing ControlPlaneEndpoint.Host. + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. When using a managed load balancer, this VIP will be managed automatically. - If not using a managed load balancer, cluster configuration will - fail without additional configuration to manage the VIP on the control - plane machines, which falls outside of the scope of this controller. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. type: boolean disablePortSecurity: - description: DisablePortSecurity disables the port security of the - network created for the Kubernetes cluster, which also disables - SecurityGroups + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups type: boolean dnsNameservers: - description: DNSNameservers is the list of nameservers for OpenStack - Subnet being created. Set this value when you need create a new - network/subnet while the access through DNS is required. + description: |- + DNSNameservers is the list of nameservers for OpenStack Subnet being created. + Set this value when you need create a new network/subnet while the access + through DNS is required. items: type: string type: array x-kubernetes-list-type: set externalNetworkId: - description: ExternalNetworkID is the ID of an external OpenStack - Network. This is necessary to get public internet to the VMs. + description: |- + ExternalNetworkID is the ID of an external OpenStack Network. This is necessary + to get public internet to the VMs. type: string externalRouterIPs: - description: ExternalRouterIPs is an array of externalIPs on the respective - subnets. This is necessary if the router needs a fixed ip in a specific - subnet. + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. items: properties: fixedIP: @@ -4250,26 +4319,28 @@ spec: reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by the infrastructure + description: |- + Kind of the identity. Must be supported by the infrastructure provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be used. Must - be either a cluster-scoped resource, or namespaced-scoped resource - the same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object managedSecurityGroups: - description: ManagedSecurityGroups determines whether OpenStack security - groups for the cluster will be managed by the OpenStack provider - or whether pre-existing security groups will be specified as part - of the configuration. By default, the managed security groups have - rules that allow the Kubelet, etcd, the Kubernetes API server and - the Calico CNI plugin to function correctly. + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, the + Kubernetes API server and the Calico CNI plugin to function correctly. type: boolean network: description: If NodeCIDR cannot be set this can be used to detect @@ -4293,22 +4364,22 @@ spec: type: string type: object networkMtu: - description: NetworkMTU sets the maximum transmission unit (MTU) value - to address fragmentation for the private network ID. This value - will be used only if the Cluster actuator creates the network. If - leaved empty, the network will have the default MTU defined in Openstack - network service. To use this field, the Openstack installation requires - the net-mtu neutron API extension. + description: |- + NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. + This value will be used only if the Cluster actuator creates the network. + If leaved empty, the network will have the default MTU defined in Openstack network service. + To use this field, the Openstack installation requires the net-mtu neutron API extension. type: integer nodeCidr: - description: NodeCIDR is the OpenStack Subnet to be created. Cluster - actuator will create a network, a subnet with NodeCIDR, and a router - connected to this subnet. If you leave this empty, no network will - be created. + description: |- + NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a + network, a subnet with NodeCIDR, and a router connected to this subnet. + If you leave this empty, no network will be created. type: string router: - description: If NodeCIDR is set this option can be used to detect - an existing router. If specified, no new router will be created. + description: |- + If NodeCIDR is set this option can be used to detect an existing router. + If specified, no new router will be created. properties: description: type: string @@ -4412,8 +4483,9 @@ spec: type: string type: object bastionSecurityGroup: - description: SecurityGroup represents the basic information of the - associated OpenStack Neutron Security Group. + description: |- + SecurityGroup represents the basic information of the associated + OpenStack Neutron Security Group. properties: id: type: string @@ -4421,8 +4493,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -4460,13 +4533,12 @@ spec: required: - id - name - - rules type: object controlPlaneSecurityGroup: - description: 'ControlPlaneSecurityGroups contains all the information - about the OpenStack Security Group that needs to be applied to control - plane nodes. TODO: Maybe instead of two properties, we add a property - to the group?' + description: |- + ControlPlaneSecurityGroups contains all the information about the OpenStack + Security Group that needs to be applied to control plane nodes. + TODO: Maybe instead of two properties, we add a property to the group? properties: id: type: string @@ -4474,8 +4546,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -4513,7 +4586,6 @@ spec: required: - id - name - - rules type: object externalNetwork: description: externalNetwork contains information about the external @@ -4533,9 +4605,9 @@ spec: type: object failureDomains: additionalProperties: - description: FailureDomainSpec is the Schema for Cluster API failure - domains. It allows controllers to understand how many failure - domains a cluster can optionally span across. + description: |- + FailureDomainSpec is the Schema for Cluster API failure domains. + It allows controllers to understand how many failure domains a cluster can optionally span across. properties: attributes: additionalProperties: @@ -4551,36 +4623,46 @@ spec: description: FailureDomains represent OpenStack availability zones type: object failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the OpenStackCluster and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the OpenStackCluster's spec or the configuration of the - controller, and that manual intervention is required. Examples of - terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the responsible - controller itself being critically misconfigured. \n Any transient - errors that occur during the reconciliation of OpenStackClusters - can be added as events to the OpenStackCluster object and/or logged - in the controller's output." + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. type: string failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the OpenStackCluster and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the OpenStackCluster's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of OpenStackClusters can be added - as events to the OpenStackCluster object and/or logged in the controller's - output." + description: |- + FailureReason will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a succinct value suitable + for machine interpretation. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. type: string network: description: Network contains information about the created OpenStack @@ -4644,9 +4726,9 @@ spec: - name type: object workerSecurityGroup: - description: WorkerSecurityGroup contains all the information about - the OpenStack Security Group that needs to be applied to worker - nodes. + description: |- + WorkerSecurityGroup contains all the information about the OpenStack Security + Group that needs to be applied to worker nodes. properties: id: type: string @@ -4654,8 +4736,9 @@ spec: type: string rules: items: - description: SecurityGroupRule represent the basic information - of the associated OpenStack Security Group Role. + description: |- + SecurityGroupRule represent the basic information of the associated OpenStack + Security Group Role. properties: description: type: string @@ -4693,7 +4776,2278 @@ spec: required: - id - name - - rules + type: object + required: + - ready + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Cluster to which this OpenStackCluster belongs + jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name + name: Cluster + type: string + - description: Cluster infrastructure is ready for OpenStack instances + jsonPath: .status.ready + name: Ready + type: string + - description: Network the cluster is using + jsonPath: .status.network.id + name: Network + type: string + - description: API Endpoint + jsonPath: .spec.controlPlaneEndpoint.host + name: Endpoint + priority: 1 + type: string + - description: Bastion address for breakglass access + jsonPath: .status.bastion.floatingIP + name: Bastion IP + type: string + - description: Time duration since creation of OpenStackCluster + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: OpenStackCluster is the Schema for the openstackclusters API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OpenStackClusterSpec defines the desired state of OpenStackCluster. + properties: + apiServerFixedIP: + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. + type: string + apiServerFloatingIP: + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. + This field is not used if DisableAPIServerFloatingIP is set to true. + type: string + apiServerLoadBalancer: + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + If not specified, no load balancer will be created for the API server. + properties: + additionalPorts: + description: AdditionalPorts adds additional tcp ports to the + load balancer. + items: + type: integer + type: array + x-kubernetes-list-type: set + allowedCIDRs: + description: AllowedCIDRs restrict access to all API-Server listeners + to the given address CIDRs. + items: + type: string + type: array + x-kubernetes-list-type: set + availabilityZone: + description: AvailabilityZone is the failure domain that will + be used to create the APIServerLoadBalancer Spec. + type: string + enabled: + default: true + description: |- + Enabled defines whether a load balancer should be created. This value + defaults to true if an APIServerLoadBalancer is given. + + + There is no reason to set this to false. To disable creation of the + API server loadbalancer, omit the APIServerLoadBalancer field in the + cluster spec instead. + type: boolean + network: + description: Network defines which network should the load balancer + be allocated on. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID is + provided, the other filters cannot be provided. Must be + in UUID format. + format: uuid + type: string + type: object + provider: + description: |- + Provider specifies name of a specific Octavia provider to use for the + API load balancer. The Octavia default will be used if it is not + specified. + type: string + subnets: + description: |- + Subnets define which subnets should the load balancer be allocated on. + It is expected that subnets are located on the network specified in this resource. + Only the first element is taken into account. + kubebuilder:validation:MaxLength:=2 + items: + description: SubnetParam specifies an OpenStack subnet to use. + It may be specified by either ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select the subnet. + It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will not be + validated. + format: uuid + type: string + type: object + type: array + x-kubernetes-list-type: atomic + required: + - enabled + type: object + apiServerPort: + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created + type: integer + bastion: + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. To make changes, it's required + to first set `enabled: false` which will remove the bastion and then changes can be made. + properties: + availabilityZone: + description: AvailabilityZone is the failure domain that will + be used to create the Bastion Spec. + type: string + enabled: + default: true + description: |- + Enabled means that bastion is enabled. The bastion is enabled by + default if this field is not specified. Set this field to false to disable the + bastion. + + + It is not currently possible to remove the bastion from the cluster + spec without first disabling it by setting this field to false and + waiting until the bastion has been deleted. + type: boolean + floatingIP: + description: |- + FloatingIP which will be associated to the bastion machine. It's the IP address, not UUID. + The floating IP should already exist and should not be associated with a port. If FIP of this address does not + exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so. + format: ipv4 + type: string + spec: + description: Spec for the bastion itself + properties: + additionalBlockDevices: + description: AdditionalBlockDevices is a list of specifications + for additional block devices to attach to the server instance + items: + description: AdditionalBlockDevice is a block device to + attach to the server. + properties: + name: + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack + metadata API or the config drive. + Name cannot be 'root', which is reserved for the root volume. + type: string + sizeGiB: + description: SizeGiB is the size of the block device + in gibibytes (GiB). + minimum: 1 + type: integer + storage: + description: |- + Storage specifies the storage type of the block device and + additional storage options. + properties: + type: + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". + type: string + volume: + description: Volume contains additional storage + options for a volume block device. + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' + or default + rule: '!has(self.from) || self.from == ''Name'' + ? has(self.name) : !has(self.name)' + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + type: object + required: + - type + type: object + required: + - name + - sizeGiB + - storage + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + configDrive: + description: Config Drive support + type: boolean + flavor: + description: The flavor reference for the flavor for your + server instance. + type: string + floatingIPPoolRef: + description: |- + floatingIPPoolRef is a reference to a IPPool that will be assigned + to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP + will be assigned to the OpenStackMachine. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + identityRef: + description: |- + IdentityRef is a reference to a secret holding OpenStack credentials + to be used when reconciling this machine. If not specified, the + credentials specified in the cluster will be used. + properties: + cloudName: + description: CloudName specifies the name of the entry + in the clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + image: + description: |- + The image to use for your server instance. + If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. If specified, + the combination of name and tags must return a single + matching image or an error will be raised. + type: string + tags: + description: The tags associated with the desired + image. If specified, the combination of name and + tags must return a single matching image or an error + will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the image. ID will not + be validated before use. + format: uuid + type: string + type: object + ports: + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. + items: + properties: + adminStateUp: + description: AdminStateUp specifies whether the port + should be created in the up (true) or down (false) + state. The default is up. + type: boolean + allowedAddressPairs: + description: |- + AllowedAddressPairs is a list of address pairs which Neutron will + allow the port to send traffic from in addition to the port's + addresses. If not specified, the MAC Address will be the MAC Address + of the port. Depending on the configuration of Neutron, it may be + supported to specify a CIDR instead of a specific IP address. + items: + properties: + ipAddress: + description: |- + IPAddress is the IP address of the allowed address pair. Depending on + the configuration of Neutron, it may be supported to specify a CIDR + instead of a specific IP address. + type: string + macAddress: + description: |- + MACAddress is the MAC address of the allowed address pair. If not + specified, the MAC address will be the MAC address of the port. + type: string + required: + - ipAddress + type: object + type: array + description: + description: Description is a human-readable description + for the port. + type: string + disablePortSecurity: + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. + type: boolean + fixedIPs: + description: FixedIPs is a list of pairs of subnet and/or + IP address to assign to the port. If specified, these + must be subnets of the port's network. + items: + properties: + ipAddress: + description: |- + IPAddress is a specific IP address to assign to the port. If Subnet + is also specified, IPAddress must be a valid IP address in the + subnet. If Subnet is not specified, IPAddress must be a valid IP + address in any subnet of the port's network. + type: string + subnet: + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to + select the subnet. It must match exactly + one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. + It will not be validated. + format: uuid + type: string + type: object + type: object + type: array + x-kubernetes-list-type: atomic + hostID: + description: HostID specifies the ID of the host where + the port resides. + type: string + macAddress: + description: MACAddress specifies the MAC address of + the port. If not specified, the MAC address will be + generated. + type: string + nameSuffix: + description: NameSuffix will be appended to the name + of the port if specified. If unspecified, instead + the 0-based index of the port in the list is used. + type: string + network: + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select + an OpenStack network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. + If ID is provided, the other filters cannot be + provided. Must be in UUID format. + format: uuid + type: string + type: object + profile: + description: |- + Profile is a set of key-value pairs that are used for binding + details. We intentionally don't expose this as a map[string]string + because we only want to enable the users to set the values of the + keys that are known to work in OpenStack Networking API. See + https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + To set profiles, your tenant needs permissions rule:create_port, and + rule:create_port:binding:profile + properties: + ovsHWOffload: + description: OVSHWOffload enables or disables the + OVS hardware offload feature. + type: boolean + trustedVF: + description: TrustedVF enables or disables the “trusted + mode” for the VF. + type: boolean + type: object + propagateUplinkStatus: + description: PropageteUplinkStatus enables or disables + the propagate uplink status on the port. + type: boolean + securityGroups: + description: SecurityGroups is a list of the names, + uuids, filters or any combination these of the security + groups to assign to the instance. + items: + description: SecurityGroupParam specifies an OpenStack + security group. It may be specified by ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select + an OpenStack security group. If provided, cannot + be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + type: array + x-kubernetes-list-type: atomic + tags: + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: |- + Trunk specifies whether trunking is enabled at the port level. If not + provided the value is inherited from the machine, or false for a + bastion host. + type: boolean + valueSpecs: + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. + items: + description: ValueSpec represents a single value_spec + key-value pair. + properties: + key: + description: Key is the key in the key-value pair. + type: string + name: + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. + type: string + value: + description: Value is the value in the key-value + pair. + type: string + required: + - key + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + vnicType: + description: |- + VNICType specifies the type of vNIC which this port should be + attached to. This is used to determine which mechanism driver(s) to + be used to bind the port. The valid values are normal, macvtap, + direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + remote-managed, although these values will not be validated in this + API to ensure compatibility with future neutron changes or custom + implementations. What type of vNIC is actually available depends on + deployments. If not specified, the Neutron default value is used. + type: string + type: object + type: array + providerID: + description: ProviderID is the unique identifier as specified + by the cloud provider. + type: string + rootVolume: + description: The volume metadata to boot from + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' or default + rule: '!has(self.from) || self.from == ''Name'' ? has(self.name) + : !has(self.name)' + sizeGiB: + description: SizeGiB is the size of the block device in + gibibytes (GiB). + minimum: 1 + type: integer + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + required: + - sizeGiB + type: object + securityGroups: + description: The names of the security groups to assign to + the instance + items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group to use. + If ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid + type: string + type: object + type: array + serverGroup: + description: The server group to assign the machine to. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack + server group. If provided, it cannot be empty. + minProperties: 1 + properties: + name: + description: Name is the name of a server group to + look for. + type: string + type: object + id: + description: ID is the ID of the server group to use. + format: uuid + type: string + type: object + serverMetadata: + description: Metadata mapping. Allows you to create a map + of key value pairs to add to the server instance. + items: + properties: + key: + description: Key is the server metadata key + maxLength: 255 + type: string + value: + description: Value is the server metadata value + maxLength: 255 + type: string + required: + - key + - value + type: object + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + sshKeyName: + description: The ssh key to inject in the instance + type: string + tags: + description: |- + Tags which will be added to the machine and all dependent resources + which support them. These are in addition to Tags defined on the + cluster. + Requires Nova api 2.52 minimum! + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: Whether the server instance is created on a trunk + port or not. + type: boolean + required: + - flavor + - image + type: object + type: object + x-kubernetes-validations: + - message: spec is required if bastion is enabled + rule: '!self.enabled || has(self.spec)' + controlPlaneAvailabilityZones: + description: |- + ControlPlaneAvailabilityZones is the set of availability zones which + control plane machines may be deployed to. + items: + type: string + type: array + x-kubernetes-list-type: set + controlPlaneEndpoint: + description: |- + ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. + It is normally populated automatically by the OpenStackCluster + controller during cluster provisioning. If it is set on creation the + control plane endpoint will use the values set here in preference to + values set elsewhere. + ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set. + properties: + host: + description: The hostname on which the API server is serving. + type: string + port: + description: The port on which the API server is serving. + format: int32 + type: integer + required: + - host + - port + type: object + controlPlaneOmitAvailabilityZone: + description: |- + ControlPlaneOmitAvailabilityZone causes availability zone to be + omitted when creating control plane nodes, allowing the Nova + scheduler to make a decision on which availability zone to use based + on other scheduling constraints + type: boolean + disableAPIServerFloatingIP: + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. + When using a managed load balancer, this VIP will be managed automatically. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. + type: boolean + disableExternalNetwork: + description: |- + DisableExternalNetwork specifies whether or not to attempt to connect the cluster + to an external network. This allows for the creation of clusters when connecting + to an external network is not possible or desirable, e.g. if using a provider network. + type: boolean + disablePortSecurity: + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups + type: boolean + externalNetwork: + description: |- + ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. + This option is ignored if DisableExternalNetwork is set to true. + + + If ExternalNetwork is defined it must refer to exactly one external network. + + + If ExternalNetwork is not defined or is empty the controller will use any + existing external network as long as there is only one. It is an + error if ExternalNetwork is not defined and there are multiple + external networks unless DisableExternalNetwork is also set. + + + If ExternalNetwork is not defined and there are no external networks + the controller will proceed as though DisableExternalNetwork was set. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID is provided, + the other filters cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + externalRouterIPs: + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. + items: + properties: + fixedIP: + description: The FixedIP in the corresponding subnet + type: string + subnet: + description: The subnet in which the FixedIP is used for the + Gateway of this router + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select the subnet. + It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will not be + validated. + format: uuid + type: string + type: object + required: + - subnet + type: object + type: array + x-kubernetes-list-type: atomic + identityRef: + description: |- + IdentityRef is a reference to a secret holding OpenStack credentials + to be used when reconciling this cluster. It is also to reconcile + machines unless overridden in the machine spec. + properties: + cloudName: + description: CloudName specifies the name of the entry in the + clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + managedSecurityGroups: + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, and the + Kubernetes API server to function correctly. + It's possible to add additional rules to the managed security groups. + When defined to an empty struct, the managed security groups will be created with the default rules. + properties: + allNodesSecurityGroupRules: + description: allNodesSecurityGroupRules defines the rules that + should be applied to all nodes. + items: + description: |- + SecurityGroupRuleSpec represent the basic information of the associated OpenStack + Security Group Role. + For now this is only used for the allNodesSecurityGroupRules but when we add + other security groups, we'll need to add a validation because + Remote* fields are mutually exclusive. + properties: + description: + description: description of the security group rule. + type: string + direction: + description: |- + direction in which the security group rule is applied. The only values + allowed are "ingress" or "egress". For a compute instance, an ingress + security group rule is applied to incoming (ingress) traffic for that + instance. An egress rule is applied to traffic leaving the instance. + type: string + etherType: + description: |- + etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the + ingress or egress rules. + type: string + name: + description: |- + name of the security group rule. + It's used to identify the rule so it can be patched and will not be sent to the OpenStack API. + type: string + portRangeMax: + description: |- + portRangeMax is a number in the range that is matched by the security group + rule. The portRangeMin attribute constrains the portRangeMax attribute. + type: integer + portRangeMin: + description: |- + portRangeMin is a number in the range that is matched by the security group + rule. If the protocol is TCP or UDP, this value must be less than or equal + to the value of the portRangeMax attribute. + type: integer + protocol: + description: protocol is the protocol that is matched by + the security group rule. + type: string + remoteGroupID: + description: |- + remoteGroupID is the remote group ID to be associated with this security group rule. + You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + type: string + remoteIPPrefix: + description: |- + remoteIPPrefix is the remote IP prefix to be associated with this security group rule. + You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + type: string + remoteManagedGroups: + description: |- + remoteManagedGroups is the remote managed groups to be associated with this security group rule. + You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + items: + enum: + - bastion + - controlplane + - worker + type: string + type: array + required: + - direction + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + allowAllInClusterTraffic: + default: false + description: AllowAllInClusterTraffic allows all ingress and egress + traffic between cluster nodes when set to true. + type: boolean + required: + - allowAllInClusterTraffic + type: object + managedSubnets: + description: |- + ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network, + subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4 + subnet is supported. If you leave this empty, no network will be created. + items: + properties: + allocationPools: + description: |- + AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. + If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from + outside of these ranges manually. + items: + properties: + end: + description: End represents the end of the AlloctionPool, + that is the highest IP of the pool. + type: string + start: + description: Start represents the start of the AllocationPool, + that is the lowest IP of the pool. + type: string + required: + - end + - start + type: object + type: array + cidr: + description: |- + CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24. + This field is required when defining a subnet. + type: string + dnsNameservers: + description: |- + DNSNameservers holds a list of DNS server addresses that will be provided when creating + the subnet. These addresses need to have the same IP version as CIDR. + items: + type: string + type: array + required: + - cidr + type: object + maxItems: 1 + type: array + x-kubernetes-list-type: atomic + network: + description: |- + Network specifies an existing network to use if no ManagedSubnets + are specified. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID is provided, + the other filters cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + networkMTU: + description: |- + NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. + This value will be used only if the Cluster actuator creates the network. + If left empty, the network will have the default MTU defined in Openstack network service. + To use this field, the Openstack installation requires the net-mtu neutron API extension. + type: integer + router: + description: |- + Router specifies an existing router to be used if ManagedSubnets are + specified. If specified, no new router will be created. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + router. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the router to use. If ID is provided, + the other filters cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + subnets: + description: |- + Subnets specifies existing subnets to use if not ManagedSubnets are + specified. All subnets must be in the network specified by Network. + There can be zero, one, or two subnets. If no subnets are specified, + all subnets in Network will be used. If 2 subnets are specified, one + must be IPv4 and the other IPv6. + items: + description: SubnetParam specifies an OpenStack subnet to use. It + may be specified by either ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select the subnet. + It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will not be validated. + format: uuid + type: string + type: object + maxItems: 2 + type: array + x-kubernetes-list-type: atomic + tags: + description: Tags to set on all resources in cluster which support + tags + items: + type: string + type: array + x-kubernetes-list-type: set + required: + - identityRef + type: object + status: + description: OpenStackClusterStatus defines the observed state of OpenStackCluster. + properties: + apiServerLoadBalancer: + description: APIServerLoadBalancer describes the api server load balancer + if one exists + properties: + allowedCIDRs: + items: + type: string + type: array + id: + type: string + internalIP: + type: string + ip: + type: string + loadBalancerNetwork: + description: |- + LoadBalancerNetwork contains information about network and/or subnets which the + loadbalancer is allocated on. + If subnets are specified within the LoadBalancerNetwork currently only the first + subnet in the list is taken into account. + properties: + id: + type: string + name: + type: string + subnets: + description: Subnets is a list of subnets associated with + the default cluster network. Machines which use the default + cluster network will get an address from all of these subnets. + items: + description: Subnet represents basic information about the + associated OpenStack Neutron Subnet. + properties: + cidr: + type: string + id: + type: string + name: + type: string + tags: + items: + type: string + type: array + required: + - cidr + - id + - name + type: object + type: array + tags: + items: + type: string + type: array + required: + - id + - name + type: object + name: + type: string + tags: + items: + type: string + type: array + required: + - id + - internalIP + - ip + - name + type: object + bastion: + description: Bastion contains the information about the deployed bastion + host + properties: + floatingIP: + type: string + id: + type: string + ip: + type: string + name: + type: string + resolved: + description: |- + Resolved contains parts of the bastion's machine spec with all + external references fully resolved. + properties: + imageID: + description: ImageID is the ID of the image to use for the + machine and is calculated based on ImageFilter. + type: string + ports: + description: Ports is the fully resolved list of ports to + create for the machine. + items: + description: ResolvedPortSpec is a PortOpts with all contained + references fully resolved. + properties: + adminStateUp: + description: AdminStateUp specifies whether the port + should be created in the up (true) or down (false) + state. The default is up. + type: boolean + allowedAddressPairs: + description: |- + AllowedAddressPairs is a list of address pairs which Neutron will + allow the port to send traffic from in addition to the port's + addresses. If not specified, the MAC Address will be the MAC Address + of the port. Depending on the configuration of Neutron, it may be + supported to specify a CIDR instead of a specific IP address. + items: + properties: + ipAddress: + description: |- + IPAddress is the IP address of the allowed address pair. Depending on + the configuration of Neutron, it may be supported to specify a CIDR + instead of a specific IP address. + type: string + macAddress: + description: |- + MACAddress is the MAC address of the allowed address pair. If not + specified, the MAC address will be the MAC address of the port. + type: string + required: + - ipAddress + type: object + type: array + description: + description: Description is a human-readable description + for the port. + type: string + disablePortSecurity: + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. + type: boolean + fixedIPs: + description: FixedIPs is a list of pairs of subnet and/or + IP address to assign to the port. If specified, these + must be subnets of the port's network. + items: + description: ResolvedFixedIP is a FixedIP with the + Subnet resolved to an ID. + properties: + ipAddress: + description: |- + IPAddress is a specific IP address to assign to the port. If SubnetID + is also specified, IPAddress must be a valid IP address in the + subnet. If Subnet is not specified, IPAddress must be a valid IP + address in any subnet of the port's network. + type: string + subnet: + description: SubnetID is the id of a subnet to + create the fixed IP of a port in. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + hostID: + description: HostID specifies the ID of the host where + the port resides. + type: string + macAddress: + description: MACAddress specifies the MAC address of + the port. If not specified, the MAC address will be + generated. + type: string + name: + description: Name is the name of the port. + type: string + networkID: + description: NetworkID is the ID of the network the + port will be created in. + type: string + profile: + description: |- + Profile is a set of key-value pairs that are used for binding + details. We intentionally don't expose this as a map[string]string + because we only want to enable the users to set the values of the + keys that are known to work in OpenStack Networking API. See + https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + To set profiles, your tenant needs permissions rule:create_port, and + rule:create_port:binding:profile + properties: + ovsHWOffload: + description: OVSHWOffload enables or disables the + OVS hardware offload feature. + type: boolean + trustedVF: + description: TrustedVF enables or disables the “trusted + mode” for the VF. + type: boolean + type: object + propagateUplinkStatus: + description: PropageteUplinkStatus enables or disables + the propagate uplink status on the port. + type: boolean + securityGroups: + description: SecurityGroups is a list of security group + IDs to assign to the port. + items: + type: string + type: array + x-kubernetes-list-type: atomic + tags: + description: Tags applied to the port (and corresponding + trunk, if a trunk is configured.) + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: Trunk specifies whether trunking is enabled + at the port level. + type: boolean + valueSpecs: + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. + items: + description: ValueSpec represents a single value_spec + key-value pair. + properties: + key: + description: Key is the key in the key-value pair. + type: string + name: + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. + type: string + value: + description: Value is the value in the key-value + pair. + type: string + required: + - key + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + vnicType: + description: |- + VNICType specifies the type of vNIC which this port should be + attached to. This is used to determine which mechanism driver(s) to + be used to bind the port. The valid values are normal, macvtap, + direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + remote-managed, although these values will not be validated in this + API to ensure compatibility with future neutron changes or custom + implementations. What type of vNIC is actually available depends on + deployments. If not specified, the Neutron default value is used. + type: string + required: + - description + - name + - networkID + type: object + type: array + serverGroupID: + description: ServerGroupID is the ID of the server group the + machine should be added to and is calculated based on ServerGroupFilter. + type: string + type: object + resources: + description: Resources contains references to OpenStack resources + created for the bastion. + properties: + ports: + description: Ports is the status of the ports created for + the machine. + items: + properties: + id: + description: ID is the unique identifier of the port. + type: string + required: + - id + type: object + type: array + type: object + sshKeyName: + type: string + state: + description: InstanceState describes the state of an OpenStack + instance. + type: string + type: object + bastionSecurityGroup: + description: |- + BastionSecurityGroup contains the information about the OpenStack + Security Group that needs to be applied to worker nodes. + properties: + id: + description: id of the security group + type: string + name: + description: name of the security group + type: string + required: + - id + - name + type: object + controlPlaneSecurityGroup: + description: |- + ControlPlaneSecurityGroup contains the information about the + OpenStack Security Group that needs to be applied to control plane + nodes. + properties: + id: + description: id of the security group + type: string + name: + description: name of the security group + type: string + required: + - id + - name + type: object + externalNetwork: + description: ExternalNetwork contains information about the external + network used for default ingress and egress traffic. + properties: + id: + type: string + name: + type: string + tags: + items: + type: string + type: array + required: + - id + - name + type: object + failureDomains: + additionalProperties: + description: |- + FailureDomainSpec is the Schema for Cluster API failure domains. + It allows controllers to understand how many failure domains a cluster can optionally span across. + properties: + attributes: + additionalProperties: + type: string + description: Attributes is a free form map of attributes an + infrastructure provider might use or require. + type: object + controlPlane: + description: ControlPlane determines if this failure domain + is suitable for use by control plane machines. + type: boolean + type: object + description: FailureDomains represent OpenStack availability zones + type: object + failureMessage: + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. + type: string + failureReason: + description: |- + FailureReason will be set in the event that there is a terminal problem + reconciling the OpenStackCluster and will contain a succinct value suitable + for machine interpretation. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the OpenStackCluster's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of + OpenStackClusters can be added as events to the OpenStackCluster object + and/or logged in the controller's output. + type: string + network: + description: Network contains information about the created OpenStack + Network. + properties: + id: + type: string + name: + type: string + subnets: + description: Subnets is a list of subnets associated with the + default cluster network. Machines which use the default cluster + network will get an address from all of these subnets. + items: + description: Subnet represents basic information about the associated + OpenStack Neutron Subnet. + properties: + cidr: + type: string + id: + type: string + name: + type: string + tags: + items: + type: string + type: array + required: + - cidr + - id + - name + type: object + type: array + tags: + items: + type: string + type: array + required: + - id + - name + type: object + ready: + default: false + description: Ready is true when the cluster infrastructure is ready. + type: boolean + router: + description: Router describes the default cluster router + properties: + id: + type: string + ips: + items: + type: string + type: array + name: + type: string + tags: + items: + type: string + type: array + required: + - id + - name + type: object + workerSecurityGroup: + description: |- + WorkerSecurityGroup contains the information about the OpenStack + Security Group that needs to be applied to worker nodes. + properties: + id: + description: id of the security group + type: string + name: + description: name of the security group + type: string + required: + - id + - name type: object required: - ready diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml index 815a3a83fc..96680265b6 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: openstackclustertemplates.infrastructure.cluster.x-k8s.io spec: group: infrastructure.cluster.x-k8s.io @@ -24,18 +24,26 @@ spec: name: v1alpha5 schema: openAPIV3Schema: - description: "OpenStackClusterTemplate is the Schema for the openstackclustertemplates - API. \n Deprecated: This type will be removed in one of the next releases." + description: |- + OpenStackClusterTemplate is the Schema for the openstackclustertemplates API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -52,35 +60,34 @@ spec: OpenStackCluster. properties: allowAllInClusterTraffic: - description: AllowAllInClusterTraffic is only used when managed - security groups are in use. If set to true, the rules for - the managed security groups are configured so that all ingress - and egress between cluster nodes is permitted, allowing - CNIs other than Calico to be used. + description: |- + AllowAllInClusterTraffic is only used when managed security groups are in use. + If set to true, the rules for the managed security groups are configured so that all + ingress and egress between cluster nodes is permitted, allowing CNIs other than + Calico to be used. type: boolean apiServerFixedIP: - description: APIServerFixedIP is the fixed IP which will be - associated with the API server. In the case where the API - server has a floating IP but not a managed load balancer, - this field is not used. If a managed load balancer is used - and this field is not specified, a fixed IP will be dynamically - allocated for the load balancer. If a managed load balancer - is not used AND the API server floating IP is disabled, - this field MUST be specified and should correspond to a - pre-allocated port that holds the fixed IP to be used as - a VIP. + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. type: string apiServerFloatingIP: - description: APIServerFloatingIP is the floatingIP which will - be associated with the API server. The floatingIP will be - created if it does not already exist. If not specified, - a new floatingIP is allocated. This field is not used if - DisableAPIServerFloatingIP is set to true. + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. + This field is not used if DisableAPIServerFloatingIP is set to true. type: string apiServerLoadBalancer: - description: 'APIServerLoadBalancer configures the optional - LoadBalancer for the APIServer. It must be activated by - setting `enabled: true`.' + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + It must be activated by setting `enabled: true`. properties: additionalPorts: description: AdditionalPorts adds additional tcp ports @@ -100,14 +107,18 @@ spec: type: boolean type: object apiServerPort: - description: APIServerPort is the port on which the listener - on the APIServer will be created + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created type: integer bastion: - description: "Bastion is the OpenStack instance to login the - nodes \n As a rolling update is not ideal during a bastion - host session, we prevent changes to a running bastion configuration. - Set `enabled: false` to make changes." + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. Set `enabled: false` to + make changes. properties: availabilityZone: type: string @@ -128,50 +139,48 @@ spec: your server instance. type: string floatingIP: - description: The floatingIP which will be associated - to the machine, only used for master. The floatingIP - should have been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported - by the infrastructure provider and may be either - cluster or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity - to be used. Must be either a cluster-scoped - resource, or namespaced-scoped resource the - same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your - server instance. If the RootVolume is specified, - this will be ignored and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your - server instance. if it's empty, Image name will - be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter - when there are multiple networks defined for the - tenant. When you do not specify both networks and - ports parameters, the server attaches to the only - network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -233,28 +242,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. - If specified this will not be validated - prior to server creation. If specified, - the enclosing `NetworkParam` must also - be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If - specified this will not be validated prior - to server creation. Required if `Subnets` - specifies a subnet by UUID. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. + Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does - not already exist. When you do not specify both - networks and ports parameters, the server attaches - to the only network created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -271,10 +277,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or - disables the port security when set. When - not set, it takes the value of the corresponding - field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or @@ -285,11 +290,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet - query that will return the id of a subnet - to create the fixed IP of a port in. - This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -334,10 +337,9 @@ spec: index of the port in the list is used. type: string network: - description: Network is a query for an openstack - network that the port will be created or discovered - on. This will fail if the query returns more - than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -359,9 +361,9 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and - receive virtual network interface (VIF) port-specific + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific information to the plug-in. type: object projectId: @@ -418,10 +420,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags - are applied in addition to the instance's - tags, which will also be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -515,7 +516,9 @@ spec: compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -553,44 +556,42 @@ spec: - port type: object disableAPIServerFloatingIP: - description: DisableAPIServerFloatingIP determines whether - or not to attempt to attach a floating IP to the API server. - This allows for the creation of clusters when attaching - a floating IP to the API server (and hence, in many cases, - exposing the API server to the internet) is not possible - or desirable, e.g. if using a shared VLAN for communication - between management and workload clusters or when the management - cluster is inside the project network. This option requires - that the API server use a VIP on the cluster network so - that the underlying machines can change without changing - ControlPlaneEndpoint.Host. When using a managed load balancer, - this VIP will be managed automatically. If not using a managed - load balancer, cluster configuration will fail without additional - configuration to manage the VIP on the control plane machines, - which falls outside of the scope of this controller. + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. + When using a managed load balancer, this VIP will be managed automatically. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. type: boolean disablePortSecurity: - description: DisablePortSecurity disables the port security - of the network created for the Kubernetes cluster, which - also disables SecurityGroups + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups type: boolean dnsNameservers: - description: DNSNameservers is the list of nameservers for - OpenStack Subnet being created. Set this value when you - need create a new network/subnet while the access through - DNS is required. + description: |- + DNSNameservers is the list of nameservers for OpenStack Subnet being created. + Set this value when you need create a new network/subnet while the access + through DNS is required. items: type: string type: array externalNetworkId: - description: ExternalNetworkID is the ID of an external OpenStack - Network. This is necessary to get public internet to the - VMs. + description: |- + ExternalNetworkID is the ID of an external OpenStack Network. This is necessary + to get public internet to the VMs. type: string externalRouterIPs: - description: ExternalRouterIPs is an array of externalIPs - on the respective subnets. This is necessary if the router - needs a fixed ip in a specific subnet. + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. items: properties: fixedIP: @@ -631,10 +632,10 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must - also be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object required: @@ -646,29 +647,28 @@ spec: used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object managedSecurityGroups: - description: ManagedSecurityGroups determines whether OpenStack - security groups for the cluster will be managed by the OpenStack - provider or whether pre-existing security groups will be - specified as part of the configuration. By default, the - managed security groups have rules that allow the Kubelet, - etcd, the Kubernetes API server and the Calico CNI plugin - to function correctly. + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, the + Kubernetes API server and the Calico CNI plugin to function correctly. type: boolean network: description: If NodeCIDR cannot be set this can be used to @@ -692,10 +692,10 @@ spec: type: string type: object nodeCidr: - description: NodeCIDR is the OpenStack Subnet to be created. - Cluster actuator will create a network, a subnet with NodeCIDR, - and a router connected to this subnet. If you leave this - empty, no network will be created. + description: |- + NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a + network, a subnet with NodeCIDR, and a router connected to this subnet. + If you leave this empty, no network will be created. type: string subnet: description: If NodeCIDR cannot be set this can be used to @@ -741,23 +741,34 @@ spec: - template type: object type: object - served: true + served: false storage: false - - name: v1alpha6 + - deprecated: true + deprecationWarning: The v1alpha6 version of OpenStackClusterTemplate has been + deprecated and will be removed in a future release of the API. Please upgrade. + name: v1alpha6 schema: openAPIV3Schema: - description: OpenStackClusterTemplate is the Schema for the openstackclustertemplates - API. + description: |- + OpenStackClusterTemplate is the Schema for the openstackclustertemplates API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -774,35 +785,34 @@ spec: OpenStackCluster. properties: allowAllInClusterTraffic: - description: AllowAllInClusterTraffic is only used when managed - security groups are in use. If set to true, the rules for - the managed security groups are configured so that all ingress - and egress between cluster nodes is permitted, allowing - CNIs other than Calico to be used. + description: |- + AllowAllInClusterTraffic is only used when managed security groups are in use. + If set to true, the rules for the managed security groups are configured so that all + ingress and egress between cluster nodes is permitted, allowing CNIs other than + Calico to be used. type: boolean apiServerFixedIP: - description: APIServerFixedIP is the fixed IP which will be - associated with the API server. In the case where the API - server has a floating IP but not a managed load balancer, - this field is not used. If a managed load balancer is used - and this field is not specified, a fixed IP will be dynamically - allocated for the load balancer. If a managed load balancer - is not used AND the API server floating IP is disabled, - this field MUST be specified and should correspond to a - pre-allocated port that holds the fixed IP to be used as - a VIP. + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. type: string apiServerFloatingIP: - description: APIServerFloatingIP is the floatingIP which will - be associated with the API server. The floatingIP will be - created if it does not already exist. If not specified, - a new floatingIP is allocated. This field is not used if - DisableAPIServerFloatingIP is set to true. + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. + This field is not used if DisableAPIServerFloatingIP is set to true. type: string apiServerLoadBalancer: - description: 'APIServerLoadBalancer configures the optional - LoadBalancer for the APIServer. It must be activated by - setting `enabled: true`.' + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + It must be activated by setting `enabled: true`. properties: additionalPorts: description: AdditionalPorts adds additional tcp ports @@ -825,14 +835,18 @@ spec: type: string type: object apiServerPort: - description: APIServerPort is the port on which the listener - on the APIServer will be created + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created type: integer bastion: - description: "Bastion is the OpenStack instance to login the - nodes \n As a rolling update is not ideal during a bastion - host session, we prevent changes to a running bastion configuration. - Set `enabled: false` to make changes." + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. Set `enabled: false` to + make changes. properties: availabilityZone: type: string @@ -853,50 +867,48 @@ spec: your server instance. type: string floatingIP: - description: The floatingIP which will be associated - to the machine, only used for master. The floatingIP - should have been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported - by the infrastructure provider and may be either - cluster or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity - to be used. Must be either a cluster-scoped - resource, or namespaced-scoped resource the - same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your - server instance. If the RootVolume is specified, - this will be ignored and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your - server instance. if it's empty, Image name will - be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter - when there are multiple networks defined for the - tenant. When you do not specify both networks and - ports parameters, the server attaches to the only - network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -958,28 +970,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. - If specified this will not be validated - prior to server creation. If specified, - the enclosing `NetworkParam` must also - be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If - specified this will not be validated prior - to server creation. Required if `Subnets` - specifies a subnet by UUID. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. + Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does - not already exist. When you do not specify both - networks and ports parameters, the server attaches - to the only network created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -996,10 +1005,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or - disables the port security when set. When - not set, it takes the value of the corresponding - field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or @@ -1010,11 +1018,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet - query that will return the id of a subnet - to create the fixed IP of a port in. - This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -1059,10 +1065,9 @@ spec: index of the port in the list is used. type: string network: - description: Network is a query for an openstack - network that the port will be created or discovered - on. This will fail if the query returns more - than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -1084,9 +1089,9 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and - receive virtual network interface (VIF) port-specific + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific information to the plug-in. type: object projectId: @@ -1144,10 +1149,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags - are applied in addition to the instance's - tags, which will also be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1160,11 +1164,10 @@ spec: is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters - to include in the API request with OpenStack. - This is an extension point for the API, so - what they do and if they are supported, depends - on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -1174,10 +1177,9 @@ spec: pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the - pair and will not be sent to the OpenStack - API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the @@ -1275,7 +1277,9 @@ spec: compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -1315,50 +1319,48 @@ spec: - port type: object controlPlaneOmitAvailabilityZone: - description: Indicates whether to omit the az for control - plane nodes, allowing the Nova scheduler to make a decision - on which az to use based on other scheduling constraints + description: |- + Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler + to make a decision on which az to use based on other scheduling constraints type: boolean disableAPIServerFloatingIP: - description: DisableAPIServerFloatingIP determines whether - or not to attempt to attach a floating IP to the API server. - This allows for the creation of clusters when attaching - a floating IP to the API server (and hence, in many cases, - exposing the API server to the internet) is not possible - or desirable, e.g. if using a shared VLAN for communication - between management and workload clusters or when the management - cluster is inside the project network. This option requires - that the API server use a VIP on the cluster network so - that the underlying machines can change without changing - ControlPlaneEndpoint.Host. When using a managed load balancer, - this VIP will be managed automatically. If not using a managed - load balancer, cluster configuration will fail without additional - configuration to manage the VIP on the control plane machines, - which falls outside of the scope of this controller. + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. + When using a managed load balancer, this VIP will be managed automatically. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. type: boolean disablePortSecurity: - description: DisablePortSecurity disables the port security - of the network created for the Kubernetes cluster, which - also disables SecurityGroups + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups type: boolean dnsNameservers: - description: DNSNameservers is the list of nameservers for - OpenStack Subnet being created. Set this value when you - need create a new network/subnet while the access through - DNS is required. + description: |- + DNSNameservers is the list of nameservers for OpenStack Subnet being created. + Set this value when you need create a new network/subnet while the access + through DNS is required. items: type: string type: array x-kubernetes-list-type: set externalNetworkId: - description: ExternalNetworkID is the ID of an external OpenStack - Network. This is necessary to get public internet to the - VMs. + description: |- + ExternalNetworkID is the ID of an external OpenStack Network. This is necessary + to get public internet to the VMs. type: string externalRouterIPs: - description: ExternalRouterIPs is an array of externalIPs - on the respective subnets. This is necessary if the router - needs a fixed ip in a specific subnet. + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. items: properties: fixedIP: @@ -1399,10 +1401,10 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must - also be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object required: @@ -1414,29 +1416,28 @@ spec: used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object managedSecurityGroups: - description: ManagedSecurityGroups determines whether OpenStack - security groups for the cluster will be managed by the OpenStack - provider or whether pre-existing security groups will be - specified as part of the configuration. By default, the - managed security groups have rules that allow the Kubelet, - etcd, the Kubernetes API server and the Calico CNI plugin - to function correctly. + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, the + Kubernetes API server and the Calico CNI plugin to function correctly. type: boolean network: description: If NodeCIDR cannot be set this can be used to @@ -1460,10 +1461,10 @@ spec: type: string type: object nodeCidr: - description: NodeCIDR is the OpenStack Subnet to be created. - Cluster actuator will create a network, a subnet with NodeCIDR, - and a router connected to this subnet. If you leave this - empty, no network will be created. + description: |- + NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a + network, a subnet with NodeCIDR, and a router connected to this subnet. + If you leave this empty, no network will be created. type: string subnet: description: If NodeCIDR cannot be set this can be used to @@ -1519,14 +1520,19 @@ spec: API. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -1543,35 +1549,34 @@ spec: OpenStackCluster. properties: allowAllInClusterTraffic: - description: AllowAllInClusterTraffic is only used when managed - security groups are in use. If set to true, the rules for - the managed security groups are configured so that all ingress - and egress between cluster nodes is permitted, allowing - CNIs other than Calico to be used. + description: |- + AllowAllInClusterTraffic is only used when managed security groups are in use. + If set to true, the rules for the managed security groups are configured so that all + ingress and egress between cluster nodes is permitted, allowing CNIs other than + Calico to be used. type: boolean apiServerFixedIP: - description: APIServerFixedIP is the fixed IP which will be - associated with the API server. In the case where the API - server has a floating IP but not a managed load balancer, - this field is not used. If a managed load balancer is used - and this field is not specified, a fixed IP will be dynamically - allocated for the load balancer. If a managed load balancer - is not used AND the API server floating IP is disabled, - this field MUST be specified and should correspond to a - pre-allocated port that holds the fixed IP to be used as - a VIP. + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. type: string apiServerFloatingIP: - description: APIServerFloatingIP is the floatingIP which will - be associated with the API server. The floatingIP will be - created if it does not already exist. If not specified, - a new floatingIP is allocated. This field is not used if - DisableAPIServerFloatingIP is set to true. + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. + This field is not used if DisableAPIServerFloatingIP is set to true. type: string apiServerLoadBalancer: - description: 'APIServerLoadBalancer configures the optional - LoadBalancer for the APIServer. It must be activated by - setting `enabled: true`.' + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + It must be activated by setting `enabled: true`. properties: additionalPorts: description: AdditionalPorts adds additional tcp ports @@ -1594,14 +1599,18 @@ spec: type: string type: object apiServerPort: - description: APIServerPort is the port on which the listener - on the APIServer will be created + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created type: integer bastion: - description: "Bastion is the OpenStack instance to login the - nodes \n As a rolling update is not ideal during a bastion - host session, we prevent changes to a running bastion configuration. - Set `enabled: false` to make changes." + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. Set `enabled: false` to + make changes. properties: availabilityZone: type: string @@ -1619,13 +1628,12 @@ spec: to attach to the server. properties: name: - description: Name of the block device in the - context of a machine. If the block device - is a volume, the Cinder volume will be named - as a combination of the machine name and this - name. Also, this name will be used for tagging - the block device. Information about the block - device tag can be obtained from the OpenStack + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack metadata API or the config drive. type: string sizeGiB: @@ -1633,35 +1641,31 @@ spec: device in gibibytes (GiB). type: integer storage: - description: Storage specifies the storage type - of the block device and additional storage - options. + description: |- + Storage specifies the storage type of the block device and + additional storage options. properties: type: - description: Type is the type of block device - to create. This can be either "Volume" - or "Local". + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". type: string volume: description: Volume contains additional storage options for a volume block device. properties: availabilityZone: - description: AvailabilityZone is the - volume availability zone to create - the volume in. If omitted, the availability - zone of the server will be used. The - availability zone must NOT contain - spaces otherwise it will lead to volume - that belongs to this availability - zone register failure, see kubernetes/cloud-provider-openstack#1379 - for further information. + description: |- + AvailabilityZone is the volume availability zone to create the volume in. + If omitted, the availability zone of the server will be used. + The availability zone must NOT contain spaces otherwise it will lead to volume that belongs + to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for + further information. type: string type: - description: Type is the Cinder volume - type of the volume. If omitted, the - default Cinder volume type that is - configured in the OpenStack cloud + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud will be used. type: string type: object @@ -1689,49 +1693,49 @@ spec: your server instance. type: string floatingIP: - description: The floatingIP which will be associated - to the machine, only used for master. The floatingIP - should have been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: - description: IdentityRef is a reference to a identity - to be used when reconciling this cluster + description: |- + IdentityRef is a reference to a identity to be used when reconciling this cluster. + If not specified, the identity ref of the cluster will be used instead. properties: kind: - description: Kind of the identity. Must be supported - by the infrastructure provider and may be either - cluster or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity - to be used. Must be either a cluster-scoped - resource, or namespaced-scoped resource the - same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your - server instance. If the RootVolume is specified, - this will be ignored and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your - server instance. if it's empty, Image name will - be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does - not already exist. If not specified a default port - will be added for the default cluster network. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. items: properties: adminStateUp: @@ -1748,10 +1752,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or - disables the port security when set. When - not set, it takes the value of the corresponding - field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or @@ -1762,11 +1765,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet - query that will return the id of a subnet - to create the fixed IP of a port in. - This query must not return more than - one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -1811,10 +1812,9 @@ spec: index of the port in the list is used. type: string network: - description: Network is a query for an openstack - network that the port will be created or discovered - on. This will fail if the query returns more - than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -1834,12 +1834,11 @@ spec: type: string type: object profile: - description: Profile is a set of key-value pairs - that are used for binding details. We intentionally - don't expose this as a map[string]string because - we only want to enable the users to set the - values of the keys that are known to work - in OpenStack Networking API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + description: |- + Profile is a set of key-value pairs that are used for binding details. + We intentionally don't expose this as a map[string]string because we only want to enable + the users to set the values of the keys that are known to work in OpenStack Networking API. + See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port properties: ovsHWOffload: description: OVSHWOffload enables or disables @@ -1880,10 +1879,9 @@ spec: type: object type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags - are applied in addition to the instance's - tags, which will also be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1894,11 +1892,10 @@ spec: is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters - to include in the API request with OpenStack. - This is an extension point for the API, so - what they do and if they are supported, depends - on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -1908,10 +1905,9 @@ spec: pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the - pair and will not be sent to the OpenStack - API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the @@ -1983,7 +1979,9 @@ spec: description: The ssh key to inject in the instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -2023,50 +2021,48 @@ spec: - port type: object controlPlaneOmitAvailabilityZone: - description: Indicates whether to omit the az for control - plane nodes, allowing the Nova scheduler to make a decision - on which az to use based on other scheduling constraints + description: |- + Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler + to make a decision on which az to use based on other scheduling constraints type: boolean disableAPIServerFloatingIP: - description: DisableAPIServerFloatingIP determines whether - or not to attempt to attach a floating IP to the API server. - This allows for the creation of clusters when attaching - a floating IP to the API server (and hence, in many cases, - exposing the API server to the internet) is not possible - or desirable, e.g. if using a shared VLAN for communication - between management and workload clusters or when the management - cluster is inside the project network. This option requires - that the API server use a VIP on the cluster network so - that the underlying machines can change without changing - ControlPlaneEndpoint.Host. When using a managed load balancer, - this VIP will be managed automatically. If not using a managed - load balancer, cluster configuration will fail without additional - configuration to manage the VIP on the control plane machines, - which falls outside of the scope of this controller. + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. + When using a managed load balancer, this VIP will be managed automatically. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. type: boolean disablePortSecurity: - description: DisablePortSecurity disables the port security - of the network created for the Kubernetes cluster, which - also disables SecurityGroups + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups type: boolean dnsNameservers: - description: DNSNameservers is the list of nameservers for - OpenStack Subnet being created. Set this value when you - need create a new network/subnet while the access through - DNS is required. + description: |- + DNSNameservers is the list of nameservers for OpenStack Subnet being created. + Set this value when you need create a new network/subnet while the access + through DNS is required. items: type: string type: array x-kubernetes-list-type: set externalNetworkId: - description: ExternalNetworkID is the ID of an external OpenStack - Network. This is necessary to get public internet to the - VMs. + description: |- + ExternalNetworkID is the ID of an external OpenStack Network. This is necessary + to get public internet to the VMs. type: string externalRouterIPs: - description: ExternalRouterIPs is an array of externalIPs - on the respective subnets. This is necessary if the router - needs a fixed ip in a specific subnet. + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. items: properties: fixedIP: @@ -2112,29 +2108,28 @@ spec: used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object managedSecurityGroups: - description: ManagedSecurityGroups determines whether OpenStack - security groups for the cluster will be managed by the OpenStack - provider or whether pre-existing security groups will be - specified as part of the configuration. By default, the - managed security groups have rules that allow the Kubelet, - etcd, the Kubernetes API server and the Calico CNI plugin - to function correctly. + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, the + Kubernetes API server and the Calico CNI plugin to function correctly. type: boolean network: description: If NodeCIDR cannot be set this can be used to @@ -2158,24 +2153,22 @@ spec: type: string type: object networkMtu: - description: NetworkMTU sets the maximum transmission unit - (MTU) value to address fragmentation for the private network - ID. This value will be used only if the Cluster actuator - creates the network. If leaved empty, the network will have - the default MTU defined in Openstack network service. To - use this field, the Openstack installation requires the - net-mtu neutron API extension. + description: |- + NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. + This value will be used only if the Cluster actuator creates the network. + If leaved empty, the network will have the default MTU defined in Openstack network service. + To use this field, the Openstack installation requires the net-mtu neutron API extension. type: integer nodeCidr: - description: NodeCIDR is the OpenStack Subnet to be created. - Cluster actuator will create a network, a subnet with NodeCIDR, - and a router connected to this subnet. If you leave this - empty, no network will be created. + description: |- + NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a + network, a subnet with NodeCIDR, and a router connected to this subnet. + If you leave this empty, no network will be created. type: string router: - description: If NodeCIDR is set this option can be used to - detect an existing router. If specified, no new router will - be created. + description: |- + If NodeCIDR is set this option can be used to detect an existing router. + If specified, no new router will be created. properties: description: type: string @@ -2240,4 +2233,1806 @@ spec: type: object type: object served: true + storage: false + - name: v1beta1 + schema: + openAPIV3Schema: + description: OpenStackClusterTemplate is the Schema for the openstackclustertemplates + API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OpenStackClusterTemplateSpec defines the desired state of + OpenStackClusterTemplate. + properties: + template: + description: OpenStackClusterTemplateResource describes the data needed + to create a OpenStackCluster from a template. + properties: + spec: + description: OpenStackClusterSpec defines the desired state of + OpenStackCluster. + properties: + apiServerFixedIP: + description: |- + APIServerFixedIP is the fixed IP which will be associated with the API server. + In the case where the API server has a floating IP but not a managed load balancer, + this field is not used. + If a managed load balancer is used and this field is not specified, a fixed IP will + be dynamically allocated for the load balancer. + If a managed load balancer is not used AND the API server floating IP is disabled, + this field MUST be specified and should correspond to a pre-allocated port that + holds the fixed IP to be used as a VIP. + type: string + apiServerFloatingIP: + description: |- + APIServerFloatingIP is the floatingIP which will be associated with the API server. + The floatingIP will be created if it does not already exist. + If not specified, a new floatingIP is allocated. + This field is not used if DisableAPIServerFloatingIP is set to true. + type: string + apiServerLoadBalancer: + description: |- + APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. + If not specified, no load balancer will be created for the API server. + properties: + additionalPorts: + description: AdditionalPorts adds additional tcp ports + to the load balancer. + items: + type: integer + type: array + x-kubernetes-list-type: set + allowedCIDRs: + description: AllowedCIDRs restrict access to all API-Server + listeners to the given address CIDRs. + items: + type: string + type: array + x-kubernetes-list-type: set + availabilityZone: + description: AvailabilityZone is the failure domain that + will be used to create the APIServerLoadBalancer Spec. + type: string + enabled: + default: true + description: |- + Enabled defines whether a load balancer should be created. This value + defaults to true if an APIServerLoadBalancer is given. + + + There is no reason to set this to false. To disable creation of the + API server loadbalancer, omit the APIServerLoadBalancer field in the + cluster spec instead. + type: boolean + network: + description: Network defines which network should the + load balancer be allocated on. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an + OpenStack network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If + ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid + type: string + type: object + provider: + description: |- + Provider specifies name of a specific Octavia provider to use for the + API load balancer. The Octavia default will be used if it is not + specified. + type: string + subnets: + description: |- + Subnets define which subnets should the load balancer be allocated on. + It is expected that subnets are located on the network specified in this resource. + Only the first element is taken into account. + kubebuilder:validation:MaxLength:=2 + items: + description: SubnetParam specifies an OpenStack subnet + to use. It may be specified by either ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select + the subnet. It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will + not be validated. + format: uuid + type: string + type: object + type: array + x-kubernetes-list-type: atomic + required: + - enabled + type: object + apiServerPort: + description: |- + APIServerPort is the port on which the listener on the APIServer + will be created + type: integer + bastion: + description: |- + Bastion is the OpenStack instance to login the nodes + + + As a rolling update is not ideal during a bastion host session, we + prevent changes to a running bastion configuration. To make changes, it's required + to first set `enabled: false` which will remove the bastion and then changes can be made. + properties: + availabilityZone: + description: AvailabilityZone is the failure domain that + will be used to create the Bastion Spec. + type: string + enabled: + default: true + description: |- + Enabled means that bastion is enabled. The bastion is enabled by + default if this field is not specified. Set this field to false to disable the + bastion. + + + It is not currently possible to remove the bastion from the cluster + spec without first disabling it by setting this field to false and + waiting until the bastion has been deleted. + type: boolean + floatingIP: + description: |- + FloatingIP which will be associated to the bastion machine. It's the IP address, not UUID. + The floating IP should already exist and should not be associated with a port. If FIP of this address does not + exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so. + format: ipv4 + type: string + spec: + description: Spec for the bastion itself + properties: + additionalBlockDevices: + description: AdditionalBlockDevices is a list of specifications + for additional block devices to attach to the server + instance + items: + description: AdditionalBlockDevice is a block device + to attach to the server. + properties: + name: + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack + metadata API or the config drive. + Name cannot be 'root', which is reserved for the root volume. + type: string + sizeGiB: + description: SizeGiB is the size of the block + device in gibibytes (GiB). + minimum: 1 + type: integer + storage: + description: |- + Storage specifies the storage type of the block device and + additional storage options. + properties: + type: + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". + type: string + volume: + description: Volume contains additional + storage options for a volume block device. + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from + is 'Name' or default + rule: '!has(self.from) || self.from + == ''Name'' ? has(self.name) : !has(self.name)' + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + type: object + required: + - type + type: object + required: + - name + - sizeGiB + - storage + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + configDrive: + description: Config Drive support + type: boolean + flavor: + description: The flavor reference for the flavor for + your server instance. + type: string + floatingIPPoolRef: + description: |- + floatingIPPoolRef is a reference to a IPPool that will be assigned + to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP + will be assigned to the OpenStackMachine. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + identityRef: + description: |- + IdentityRef is a reference to a secret holding OpenStack credentials + to be used when reconciling this machine. If not specified, the + credentials specified in the cluster will be used. + properties: + cloudName: + description: CloudName specifies the name of the + entry in the clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + image: + description: |- + The image to use for your server instance. + If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. + If specified, the combination of name and + tags must return a single matching image + or an error will be raised. + type: string + tags: + description: The tags associated with the + desired image. If specified, the combination + of name and tags must return a single matching + image or an error will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the image. ID will + not be validated before use. + format: uuid + type: string + type: object + ports: + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. + items: + properties: + adminStateUp: + description: AdminStateUp specifies whether + the port should be created in the up (true) + or down (false) state. The default is up. + type: boolean + allowedAddressPairs: + description: |- + AllowedAddressPairs is a list of address pairs which Neutron will + allow the port to send traffic from in addition to the port's + addresses. If not specified, the MAC Address will be the MAC Address + of the port. Depending on the configuration of Neutron, it may be + supported to specify a CIDR instead of a specific IP address. + items: + properties: + ipAddress: + description: |- + IPAddress is the IP address of the allowed address pair. Depending on + the configuration of Neutron, it may be supported to specify a CIDR + instead of a specific IP address. + type: string + macAddress: + description: |- + MACAddress is the MAC address of the allowed address pair. If not + specified, the MAC address will be the MAC address of the port. + type: string + required: + - ipAddress + type: object + type: array + description: + description: Description is a human-readable + description for the port. + type: string + disablePortSecurity: + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. + type: boolean + fixedIPs: + description: FixedIPs is a list of pairs of + subnet and/or IP address to assign to the + port. If specified, these must be subnets + of the port's network. + items: + properties: + ipAddress: + description: |- + IPAddress is a specific IP address to assign to the port. If Subnet + is also specified, IPAddress must be a valid IP address in the + subnet. If Subnet is not specified, IPAddress must be a valid IP + address in any subnet of the port's network. + type: string + subnet: + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter + to select the subnet. It must match + exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the + subnet. It will not be validated. + format: uuid + type: string + type: object + type: object + type: array + x-kubernetes-list-type: atomic + hostID: + description: HostID specifies the ID of the + host where the port resides. + type: string + macAddress: + description: MACAddress specifies the MAC address + of the port. If not specified, the MAC address + will be generated. + type: string + nameSuffix: + description: NameSuffix will be appended to + the name of the port if specified. If unspecified, + instead the 0-based index of the port in the + list is used. + type: string + network: + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to + select an OpenStack network. If provided, + cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + profile: + description: |- + Profile is a set of key-value pairs that are used for binding + details. We intentionally don't expose this as a map[string]string + because we only want to enable the users to set the values of the + keys that are known to work in OpenStack Networking API. See + https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + To set profiles, your tenant needs permissions rule:create_port, and + rule:create_port:binding:profile + properties: + ovsHWOffload: + description: OVSHWOffload enables or disables + the OVS hardware offload feature. + type: boolean + trustedVF: + description: TrustedVF enables or disables + the “trusted mode” for the VF. + type: boolean + type: object + propagateUplinkStatus: + description: PropageteUplinkStatus enables or + disables the propagate uplink status on the + port. + type: boolean + securityGroups: + description: SecurityGroups is a list of the + names, uuids, filters or any combination these + of the security groups to assign to the instance. + items: + description: SecurityGroupParam specifies + an OpenStack security group. It may be specified + by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query + to select an OpenStack security group. + If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security + group to use. If ID is provided, the + other filters cannot be provided. Must + be in UUID format. + format: uuid + type: string + type: object + type: array + x-kubernetes-list-type: atomic + tags: + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: |- + Trunk specifies whether trunking is enabled at the port level. If not + provided the value is inherited from the machine, or false for a + bastion host. + type: boolean + valueSpecs: + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. + items: + description: ValueSpec represents a single + value_spec key-value pair. + properties: + key: + description: Key is the key in the key-value + pair. + type: string + name: + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. + type: string + value: + description: Value is the value in the + key-value pair. + type: string + required: + - key + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + vnicType: + description: |- + VNICType specifies the type of vNIC which this port should be + attached to. This is used to determine which mechanism driver(s) to + be used to bind the port. The valid values are normal, macvtap, + direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + remote-managed, although these values will not be validated in this + API to ensure compatibility with future neutron changes or custom + implementations. What type of vNIC is actually available depends on + deployments. If not specified, the Neutron default value is used. + type: string + type: object + type: array + providerID: + description: ProviderID is the unique identifier as + specified by the cloud provider. + type: string + rootVolume: + description: The volume metadata to boot from + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' + or default + rule: '!has(self.from) || self.from == ''Name'' + ? has(self.name) : !has(self.name)' + sizeGiB: + description: SizeGiB is the size of the block + device in gibibytes (GiB). + minimum: 1 + type: integer + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + required: + - sizeGiB + type: object + securityGroups: + description: The names of the security groups to assign + to the instance + items: + description: SecurityGroupParam specifies an OpenStack + security group. It may be specified by ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select + an OpenStack security group. If provided, + cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + type: array + serverGroup: + description: The server group to assign the machine + to. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select + an OpenStack server group. If provided, it cannot + be empty. + minProperties: 1 + properties: + name: + description: Name is the name of a server + group to look for. + type: string + type: object + id: + description: ID is the ID of the server group + to use. + format: uuid + type: string + type: object + serverMetadata: + description: Metadata mapping. Allows you to create + a map of key value pairs to add to the server instance. + items: + properties: + key: + description: Key is the server metadata key + maxLength: 255 + type: string + value: + description: Value is the server metadata value + maxLength: 255 + type: string + required: + - key + - value + type: object + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + sshKeyName: + description: The ssh key to inject in the instance + type: string + tags: + description: |- + Tags which will be added to the machine and all dependent resources + which support them. These are in addition to Tags defined on the + cluster. + Requires Nova api 2.52 minimum! + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: Whether the server instance is created + on a trunk port or not. + type: boolean + required: + - flavor + - image + type: object + type: object + x-kubernetes-validations: + - message: spec is required if bastion is enabled + rule: '!self.enabled || has(self.spec)' + controlPlaneAvailabilityZones: + description: |- + ControlPlaneAvailabilityZones is the set of availability zones which + control plane machines may be deployed to. + items: + type: string + type: array + x-kubernetes-list-type: set + controlPlaneEndpoint: + description: |- + ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. + It is normally populated automatically by the OpenStackCluster + controller during cluster provisioning. If it is set on creation the + control plane endpoint will use the values set here in preference to + values set elsewhere. + ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set. + properties: + host: + description: The hostname on which the API server is serving. + type: string + port: + description: The port on which the API server is serving. + format: int32 + type: integer + required: + - host + - port + type: object + controlPlaneOmitAvailabilityZone: + description: |- + ControlPlaneOmitAvailabilityZone causes availability zone to be + omitted when creating control plane nodes, allowing the Nova + scheduler to make a decision on which availability zone to use based + on other scheduling constraints + type: boolean + disableAPIServerFloatingIP: + description: |- + DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating + IP to the API server. This allows for the creation of clusters when attaching a floating + IP to the API server (and hence, in many cases, exposing the API server to the internet) + is not possible or desirable, e.g. if using a shared VLAN for communication between + management and workload clusters or when the management cluster is inside the + project network. + This option requires that the API server use a VIP on the cluster network so that the + underlying machines can change without changing ControlPlaneEndpoint.Host. + When using a managed load balancer, this VIP will be managed automatically. + If not using a managed load balancer, cluster configuration will fail without additional + configuration to manage the VIP on the control plane machines, which falls outside of + the scope of this controller. + type: boolean + disableExternalNetwork: + description: |- + DisableExternalNetwork specifies whether or not to attempt to connect the cluster + to an external network. This allows for the creation of clusters when connecting + to an external network is not possible or desirable, e.g. if using a provider network. + type: boolean + disablePortSecurity: + description: |- + DisablePortSecurity disables the port security of the network created for the + Kubernetes cluster, which also disables SecurityGroups + type: boolean + externalNetwork: + description: |- + ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. + This option is ignored if DisableExternalNetwork is set to true. + + + If ExternalNetwork is defined it must refer to exactly one external network. + + + If ExternalNetwork is not defined or is empty the controller will use any + existing external network as long as there is only one. It is an + error if ExternalNetwork is not defined and there are multiple + external networks unless DisableExternalNetwork is also set. + + + If ExternalNetwork is not defined and there are no external networks + the controller will proceed as though DisableExternalNetwork was set. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID + is provided, the other filters cannot be provided. Must + be in UUID format. + format: uuid + type: string + type: object + externalRouterIPs: + description: |- + ExternalRouterIPs is an array of externalIPs on the respective subnets. + This is necessary if the router needs a fixed ip in a specific subnet. + items: + properties: + fixedIP: + description: The FixedIP in the corresponding subnet + type: string + subnet: + description: The subnet in which the FixedIP is used + for the Gateway of this router + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select + the subnet. It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will + not be validated. + format: uuid + type: string + type: object + required: + - subnet + type: object + type: array + x-kubernetes-list-type: atomic + identityRef: + description: |- + IdentityRef is a reference to a secret holding OpenStack credentials + to be used when reconciling this cluster. It is also to reconcile + machines unless overridden in the machine spec. + properties: + cloudName: + description: CloudName specifies the name of the entry + in the clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + managedSecurityGroups: + description: |- + ManagedSecurityGroups determines whether OpenStack security groups for the cluster + will be managed by the OpenStack provider or whether pre-existing security groups will + be specified as part of the configuration. + By default, the managed security groups have rules that allow the Kubelet, etcd, and the + Kubernetes API server to function correctly. + It's possible to add additional rules to the managed security groups. + When defined to an empty struct, the managed security groups will be created with the default rules. + properties: + allNodesSecurityGroupRules: + description: allNodesSecurityGroupRules defines the rules + that should be applied to all nodes. + items: + description: |- + SecurityGroupRuleSpec represent the basic information of the associated OpenStack + Security Group Role. + For now this is only used for the allNodesSecurityGroupRules but when we add + other security groups, we'll need to add a validation because + Remote* fields are mutually exclusive. + properties: + description: + description: description of the security group rule. + type: string + direction: + description: |- + direction in which the security group rule is applied. The only values + allowed are "ingress" or "egress". For a compute instance, an ingress + security group rule is applied to incoming (ingress) traffic for that + instance. An egress rule is applied to traffic leaving the instance. + type: string + etherType: + description: |- + etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the + ingress or egress rules. + type: string + name: + description: |- + name of the security group rule. + It's used to identify the rule so it can be patched and will not be sent to the OpenStack API. + type: string + portRangeMax: + description: |- + portRangeMax is a number in the range that is matched by the security group + rule. The portRangeMin attribute constrains the portRangeMax attribute. + type: integer + portRangeMin: + description: |- + portRangeMin is a number in the range that is matched by the security group + rule. If the protocol is TCP or UDP, this value must be less than or equal + to the value of the portRangeMax attribute. + type: integer + protocol: + description: protocol is the protocol that is matched + by the security group rule. + type: string + remoteGroupID: + description: |- + remoteGroupID is the remote group ID to be associated with this security group rule. + You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + type: string + remoteIPPrefix: + description: |- + remoteIPPrefix is the remote IP prefix to be associated with this security group rule. + You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + type: string + remoteManagedGroups: + description: |- + remoteManagedGroups is the remote managed groups to be associated with this security group rule. + You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + items: + enum: + - bastion + - controlplane + - worker + type: string + type: array + required: + - direction + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + allowAllInClusterTraffic: + default: false + description: AllowAllInClusterTraffic allows all ingress + and egress traffic between cluster nodes when set to + true. + type: boolean + required: + - allowAllInClusterTraffic + type: object + managedSubnets: + description: |- + ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network, + subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4 + subnet is supported. If you leave this empty, no network will be created. + items: + properties: + allocationPools: + description: |- + AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. + If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from + outside of these ranges manually. + items: + properties: + end: + description: End represents the end of the AlloctionPool, + that is the highest IP of the pool. + type: string + start: + description: Start represents the start of the + AllocationPool, that is the lowest IP of the + pool. + type: string + required: + - end + - start + type: object + type: array + cidr: + description: |- + CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24. + This field is required when defining a subnet. + type: string + dnsNameservers: + description: |- + DNSNameservers holds a list of DNS server addresses that will be provided when creating + the subnet. These addresses need to have the same IP version as CIDR. + items: + type: string + type: array + required: + - cidr + type: object + maxItems: 1 + type: array + x-kubernetes-list-type: atomic + network: + description: |- + Network specifies an existing network to use if no ManagedSubnets + are specified. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID + is provided, the other filters cannot be provided. Must + be in UUID format. + format: uuid + type: string + type: object + networkMTU: + description: |- + NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. + This value will be used only if the Cluster actuator creates the network. + If left empty, the network will have the default MTU defined in Openstack network service. + To use this field, the Openstack installation requires the net-mtu neutron API extension. + type: integer + router: + description: |- + Router specifies an existing router to be used if ManagedSubnets are + specified. If specified, no new router will be created. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + router. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the router to use. If ID + is provided, the other filters cannot be provided. Must + be in UUID format. + format: uuid + type: string + type: object + subnets: + description: |- + Subnets specifies existing subnets to use if not ManagedSubnets are + specified. All subnets must be in the network specified by Network. + There can be zero, one, or two subnets. If no subnets are specified, + all subnets in Network will be used. If 2 subnets are specified, one + must be IPv4 and the other IPv6. + items: + description: SubnetParam specifies an OpenStack subnet to + use. It may be specified by either ID or filter, but not + both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select the + subnet. It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will not + be validated. + format: uuid + type: string + type: object + maxItems: 2 + type: array + x-kubernetes-list-type: atomic + tags: + description: Tags to set on all resources in cluster which + support tags + items: + type: string + type: array + x-kubernetes-list-type: set + required: + - identityRef + type: object + required: + - spec + type: object + required: + - template + type: object + type: object + served: true storage: true diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml new file mode 100644 index 0000000000..6de7b10f5a --- /dev/null +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml @@ -0,0 +1,250 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: openstackfloatingippools.infrastructure.cluster.x-k8s.io +spec: + group: infrastructure.cluster.x-k8s.io + names: + kind: OpenStackFloatingIPPool + listKind: OpenStackFloatingIPPoolList + plural: openstackfloatingippools + singular: openstackfloatingippool + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: OpenStackFloatingIPPool is the Schema for the openstackfloatingippools + API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OpenStackFloatingIPPoolSpec defines the desired state of + OpenStackFloatingIPPool. + properties: + floatingIPNetwork: + description: FloatingIPNetwork is the external network to use for + floating ips, if there's only one external network it will be used + by default + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID is provided, + the other filters cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + identityRef: + description: IdentityRef is a reference to a identity to be used when + reconciling this pool. + properties: + cloudName: + description: CloudName specifies the name of the entry in the + clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + maxIPs: + description: |- + MaxIPs is the maximum number of floating ips that can be allocated from this pool, if nil there is no limit. + If set, the pool will stop allocating floating ips when it reaches this number of ClaimedIPs. + type: integer + preAllocatedFloatingIPs: + description: |- + PreAllocatedFloatingIPs is a list of floating IPs precreated in OpenStack that should be used by this pool. + These are used before allocating new ones and are not deleted from OpenStack when the pool is deleted. + items: + type: string + type: array + reclaimPolicy: + description: The stratergy to use for reclaiming floating ips when + they are released from a machine + enum: + - Retain + - Delete + type: string + required: + - identityRef + - reclaimPolicy + type: object + status: + description: OpenStackFloatingIPPoolStatus defines the observed state + of OpenStackFloatingIPPool. + properties: + availableIPs: + default: [] + items: + type: string + type: array + claimedIPs: + default: [] + items: + type: string + type: array + conditions: + description: Conditions provide observations of the operational state + of a Cluster API resource. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + failedIPs: + description: FailedIPs contains a list of floating ips that failed + to be allocated + items: + type: string + type: array + floatingIPNetwork: + description: floatingIPNetwork contains information about the network + used for floating ips + properties: + id: + type: string + name: + type: string + tags: + items: + type: string + type: array + required: + - id + - name + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml index e5171cd868..243087e475 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: openstackmachines.infrastructure.cluster.x-k8s.io spec: group: infrastructure.cluster.x-k8s.io @@ -49,18 +49,26 @@ spec: name: v1alpha5 schema: openAPIV3Schema: - description: "OpenStackMachine is the Schema for the openstackmachines API. - \n Deprecated: This type will be removed in one of the next releases." + description: |- + OpenStackMachine is the Schema for the openstackmachines API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -77,45 +85,47 @@ spec: description: The flavor reference for the flavor for your server instance. type: string floatingIP: - description: The floatingIP which will be associated to the machine, - only used for master. The floatingIP should have been created and - haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by the infrastructure + description: |- + Kind of the identity. Must be supported by the infrastructure provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be used. Must - be either a cluster-scoped resource, or namespaced-scoped resource - the same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server instance. - If the RootVolume is specified, this will be ignored and use rootVolume - directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server instance. + description: |- + The uuid of the image to use for your server instance. if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter when there are - multiple networks defined for the tenant. When you do not specify - both networks and ports parameters, the server attaches to the only - network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -176,25 +186,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must also - be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If specified this - will not be validated prior to server creation. Required if - `Subnets` specifies a subnet by UUID. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. + Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. They are - created if a port with the given name does not already exist. When - you do not specify both networks and ports parameters, the server - attaches to the only network created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -211,9 +221,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -223,10 +233,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed IP - of a port in. This query must not return more than one - subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -269,9 +278,9 @@ spec: instead the 0-based index of the port in the list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -293,9 +302,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application running - on the specified host to pass and receive virtual network - interface (VIF) port-specific information to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -350,10 +360,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -442,7 +451,9 @@ spec: as AccessIPv4 on the created compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -482,37 +493,37 @@ spec: operational state. properties: lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. format: date-time type: string message: - description: A human readable message indicating details about - the transition. This field may be empty. + description: |- + A human readable message indicating details about the transition. + This field may be empty. type: string reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. type: string severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. type: string status: description: Status of the condition, one of True, False, Unknown. type: string type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. type: string required: - lastTransitionTime @@ -521,19 +532,25 @@ spec: type: object type: array failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the Machine and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the Machine's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of Machines + can be added as events to the Machine object and/or logged in the + controller's output. type: string failureReason: description: MachineStatusError defines errors states for Machine @@ -548,7 +565,7 @@ spec: type: boolean type: object type: object - served: true + served: false storage: false subresources: status: {} @@ -577,20 +594,32 @@ spec: jsonPath: .metadata.creationTimestamp name: Age type: date + deprecated: true + deprecationWarning: The v1alpha6 version of OpenStackMachine has been deprecated + and will be removed in a future release of the API. Please upgrade. name: v1alpha6 schema: openAPIV3Schema: - description: OpenStackMachine is the Schema for the openstackmachines API. + description: |- + OpenStackMachine is the Schema for the openstackmachines API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -607,45 +636,47 @@ spec: description: The flavor reference for the flavor for your server instance. type: string floatingIP: - description: The floatingIP which will be associated to the machine, - only used for master. The floatingIP should have been created and - haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by the infrastructure + description: |- + Kind of the identity. Must be supported by the infrastructure provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be used. Must - be either a cluster-scoped resource, or namespaced-scoped resource - the same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server instance. - If the RootVolume is specified, this will be ignored and use rootVolume - directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server instance. + description: |- + The uuid of the image to use for your server instance. if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter when there are - multiple networks defined for the tenant. When you do not specify - both networks and ports parameters, the server attaches to the only - network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -706,25 +737,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must also - be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If specified this - will not be validated prior to server creation. Required if - `Subnets` specifies a subnet by UUID. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. + Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. They are - created if a port with the given name does not already exist. When - you do not specify both networks and ports parameters, the server - attaches to the only network created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -741,9 +772,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -753,10 +784,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed IP - of a port in. This query must not return more than one - subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -799,9 +829,9 @@ spec: instead the 0-based index of the port in the list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -823,9 +853,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application running - on the specified host to pass and receive virtual network - interface (VIF) port-specific information to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -881,10 +912,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -896,10 +926,10 @@ spec: provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include in - the API request with OpenStack. This is an extension point - for the API, so what they do and if they are supported, depends - on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -908,9 +938,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value pair. This - is just for identifying the pair and will not be sent - to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value pair. @@ -1003,7 +1033,9 @@ spec: as AccessIPv4 on the created compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -1044,37 +1076,37 @@ spec: operational state. properties: lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. format: date-time type: string message: - description: A human readable message indicating details about - the transition. This field may be empty. + description: |- + A human readable message indicating details about the transition. + This field may be empty. type: string reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. type: string severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. type: string status: description: Status of the condition, one of True, False, Unknown. type: string type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. type: string required: - lastTransitionTime @@ -1083,19 +1115,25 @@ spec: type: object type: array failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the Machine and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the Machine's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of Machines + can be added as events to the Machine object and/or logged in the + controller's output. type: string failureReason: description: MachineStatusError defines errors states for Machine @@ -1145,14 +1183,19 @@ spec: description: OpenStackMachine is the Schema for the openstackmachines API. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -1167,23 +1210,26 @@ spec: the server. properties: name: - description: Name of the block device in the context of a machine. - If the block device is a volume, the Cinder volume will be - named as a combination of the machine name and this name. + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. Also, this name will be used for tagging the block device. - Information about the block device tag can be obtained from - the OpenStack metadata API or the config drive. + Information about the block device tag can be obtained from the OpenStack + metadata API or the config drive. type: string sizeGiB: description: SizeGiB is the size of the block device in gibibytes (GiB). type: integer storage: - description: Storage specifies the storage type of the block - device and additional storage options. + description: |- + Storage specifies the storage type of the block device and + additional storage options. properties: type: - description: Type is the type of block device to create. + description: |- + Type is the type of block device to create. This can be either "Volume" or "Local". type: string volume: @@ -1191,18 +1237,18 @@ spec: for a volume block device. properties: availabilityZone: - description: AvailabilityZone is the volume availability - zone to create the volume in. If omitted, the availability - zone of the server will be used. The availability - zone must NOT contain spaces otherwise it will lead - to volume that belongs to this availability zone register - failure, see kubernetes/cloud-provider-openstack#1379 - for further information. + description: |- + AvailabilityZone is the volume availability zone to create the volume in. + If omitted, the availability zone of the server will be used. + The availability zone must NOT contain spaces otherwise it will lead to volume that belongs + to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for + further information. type: string type: - description: Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is - configured in the OpenStack cloud will be used. + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. type: string type: object required: @@ -1227,45 +1273,48 @@ spec: description: The flavor reference for the flavor for your server instance. type: string floatingIP: - description: The floatingIP which will be associated to the machine, - only used for master. The floatingIP should have been created and - haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling this cluster + description: |- + IdentityRef is a reference to a identity to be used when reconciling this cluster. + If not specified, the identity ref of the cluster will be used instead. properties: kind: - description: Kind of the identity. Must be supported by the infrastructure + description: |- + Kind of the identity. Must be supported by the infrastructure provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be used. Must - be either a cluster-scoped resource, or namespaced-scoped resource - the same namespace as the resource(s) being provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server instance. - If the RootVolume is specified, this will be ignored and use rootVolume - directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server instance. + description: |- + The uuid of the image to use for your server instance. if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string ports: - description: Ports to be attached to the server instance. They are - created if a port with the given name does not already exist. If - not specified a default port will be added for the default cluster - network. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. items: properties: adminStateUp: @@ -1282,9 +1331,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables the port - security when set. When not set, it takes the value of the - corresponding field at the network level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. These @@ -1294,10 +1343,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query that - will return the id of a subnet to create the fixed IP - of a port in. This query must not return more than one - subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -1340,9 +1388,9 @@ spec: instead the 0-based index of the port in the list is used. type: string network: - description: Network is a query for an openstack network that - the port will be created or discovered on. This will fail - if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -1362,11 +1410,11 @@ spec: type: string type: object profile: - description: Profile is a set of key-value pairs that are used - for binding details. We intentionally don't expose this as - a map[string]string because we only want to enable the users - to set the values of the keys that are known to work in OpenStack - Networking API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + description: |- + Profile is a set of key-value pairs that are used for binding details. + We intentionally don't expose this as a map[string]string because we only want to enable + the users to set the values of the keys that are known to work in OpenStack Networking API. + See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port properties: ovsHWOffload: description: OVSHWOffload enables or disables the OVS hardware @@ -1405,10 +1453,9 @@ spec: type: object type: array tags: - description: Tags applied to the port (and corresponding trunk, - if a trunk is configured.) These tags are applied in addition - to the instance's tags, which will also be applied to the - port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1418,10 +1465,10 @@ spec: provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include in - the API request with OpenStack. This is an extension point - for the API, so what they do and if they are supported, depends - on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -1430,9 +1477,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value pair. This - is just for identifying the pair and will not be sent - to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value pair. @@ -1501,7 +1548,929 @@ spec: description: The ssh key to inject in the instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: Whether the server instance is created on a trunk port + or not. + type: boolean + required: + - flavor + type: object + status: + description: OpenStackMachineStatus defines the observed state of OpenStackMachine. + properties: + addresses: + description: Addresses contains the OpenStack instance associated + addresses. + items: + description: NodeAddress contains information for the node's address. + properties: + address: + description: The node address. + type: string + type: + description: Node address type, one of Hostname, ExternalIP + or InternalIP. + type: string + required: + - address + - type + type: object + type: array + conditions: + description: Conditions provide observations of the operational state + of a Cluster API resource. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + failureMessage: + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the Machine and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the Machine's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of Machines + can be added as events to the Machine object and/or logged in the + controller's output. + type: string + failureReason: + description: MachineStatusError defines errors states for Machine + objects. + type: string + instanceState: + description: InstanceState is the state of the OpenStack instance + for this machine. + type: string + ready: + description: Ready is true when the provider resource is ready. + type: boolean + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Cluster to which this OpenStackMachine belongs + jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name + name: Cluster + type: string + - description: OpenStack instance state + jsonPath: .status.instanceState + name: InstanceState + type: string + - description: Machine ready status + jsonPath: .status.ready + name: Ready + type: string + - description: OpenStack instance ID + jsonPath: .spec.providerID + name: ProviderID + type: string + - description: Machine object which owns with this OpenStackMachine + jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name + name: Machine + type: string + - description: Time duration since creation of OpenStackMachine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: OpenStackMachine is the Schema for the openstackmachines API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OpenStackMachineSpec defines the desired state of OpenStackMachine. + properties: + additionalBlockDevices: + description: AdditionalBlockDevices is a list of specifications for + additional block devices to attach to the server instance + items: + description: AdditionalBlockDevice is a block device to attach to + the server. + properties: + name: + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack + metadata API or the config drive. + Name cannot be 'root', which is reserved for the root volume. + type: string + sizeGiB: + description: SizeGiB is the size of the block device in gibibytes + (GiB). + minimum: 1 + type: integer + storage: + description: |- + Storage specifies the storage type of the block device and + additional storage options. + properties: + type: + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". + type: string + volume: + description: Volume contains additional storage options + for a volume block device. + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' or default + rule: '!has(self.from) || self.from == ''Name'' ? + has(self.name) : !has(self.name)' + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + type: object + required: + - type + type: object + required: + - name + - sizeGiB + - storage + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + configDrive: + description: Config Drive support + type: boolean + flavor: + description: The flavor reference for the flavor for your server instance. + type: string + floatingIPPoolRef: + description: |- + floatingIPPoolRef is a reference to a IPPool that will be assigned + to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP + will be assigned to the OpenStackMachine. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + identityRef: + description: |- + IdentityRef is a reference to a secret holding OpenStack credentials + to be used when reconciling this machine. If not specified, the + credentials specified in the cluster will be used. + properties: + cloudName: + description: CloudName specifies the name of the entry in the + clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + image: + description: |- + The image to use for your server instance. + If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. If specified, + the combination of name and tags must return a single matching + image or an error will be raised. + type: string + tags: + description: The tags associated with the desired image. If + specified, the combination of name and tags must return + a single matching image or an error will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the image. ID will not be validated + before use. + format: uuid + type: string + type: object + ports: + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. + items: + properties: + adminStateUp: + description: AdminStateUp specifies whether the port should + be created in the up (true) or down (false) state. The default + is up. + type: boolean + allowedAddressPairs: + description: |- + AllowedAddressPairs is a list of address pairs which Neutron will + allow the port to send traffic from in addition to the port's + addresses. If not specified, the MAC Address will be the MAC Address + of the port. Depending on the configuration of Neutron, it may be + supported to specify a CIDR instead of a specific IP address. + items: + properties: + ipAddress: + description: |- + IPAddress is the IP address of the allowed address pair. Depending on + the configuration of Neutron, it may be supported to specify a CIDR + instead of a specific IP address. + type: string + macAddress: + description: |- + MACAddress is the MAC address of the allowed address pair. If not + specified, the MAC address will be the MAC address of the port. + type: string + required: + - ipAddress + type: object + type: array + description: + description: Description is a human-readable description for + the port. + type: string + disablePortSecurity: + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. + type: boolean + fixedIPs: + description: FixedIPs is a list of pairs of subnet and/or IP + address to assign to the port. If specified, these must be + subnets of the port's network. + items: + properties: + ipAddress: + description: |- + IPAddress is a specific IP address to assign to the port. If Subnet + is also specified, IPAddress must be a valid IP address in the + subnet. If Subnet is not specified, IPAddress must be a valid IP + address in any subnet of the port's network. + type: string + subnet: + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select the + subnet. It must match exactly one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. It will + not be validated. + format: uuid + type: string + type: object + type: object + type: array + x-kubernetes-list-type: atomic + hostID: + description: HostID specifies the ID of the host where the port + resides. + type: string + macAddress: + description: MACAddress specifies the MAC address of the port. + If not specified, the MAC address will be generated. + type: string + nameSuffix: + description: NameSuffix will be appended to the name of the + port if specified. If unspecified, instead the 0-based index + of the port in the list is used. + type: string + network: + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select an OpenStack + network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. If ID is + provided, the other filters cannot be provided. Must be + in UUID format. + format: uuid + type: string + type: object + profile: + description: |- + Profile is a set of key-value pairs that are used for binding + details. We intentionally don't expose this as a map[string]string + because we only want to enable the users to set the values of the + keys that are known to work in OpenStack Networking API. See + https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + To set profiles, your tenant needs permissions rule:create_port, and + rule:create_port:binding:profile + properties: + ovsHWOffload: + description: OVSHWOffload enables or disables the OVS hardware + offload feature. + type: boolean + trustedVF: + description: TrustedVF enables or disables the “trusted + mode” for the VF. + type: boolean + type: object + propagateUplinkStatus: + description: PropageteUplinkStatus enables or disables the propagate + uplink status on the port. + type: boolean + securityGroups: + description: SecurityGroups is a list of the names, uuids, filters + or any combination these of the security groups to assign + to the instance. + items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group to use. + If ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid + type: string + type: object + type: array + x-kubernetes-list-type: atomic + tags: + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: |- + Trunk specifies whether trunking is enabled at the port level. If not + provided the value is inherited from the machine, or false for a + bastion host. + type: boolean + valueSpecs: + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. + items: + description: ValueSpec represents a single value_spec key-value + pair. + properties: + key: + description: Key is the key in the key-value pair. + type: string + name: + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. + type: string + value: + description: Value is the value in the key-value pair. + type: string + required: + - key + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + vnicType: + description: |- + VNICType specifies the type of vNIC which this port should be + attached to. This is used to determine which mechanism driver(s) to + be used to bind the port. The valid values are normal, macvtap, + direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + remote-managed, although these values will not be validated in this + API to ensure compatibility with future neutron changes or custom + implementations. What type of vNIC is actually available depends on + deployments. If not specified, the Neutron default value is used. + type: string + type: object + type: array + providerID: + description: ProviderID is the unique identifier as specified by the + cloud provider. + type: string + rootVolume: + description: The volume metadata to boot from + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' or default + rule: '!has(self.from) || self.from == ''Name'' ? has(self.name) + : !has(self.name)' + sizeGiB: + description: SizeGiB is the size of the block device in gibibytes + (GiB). + minimum: 1 + type: integer + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + required: + - sizeGiB + type: object + securityGroups: + description: The names of the security groups to assign to the instance + items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group to use. If ID + is provided, the other filters cannot be provided. Must be + in UUID format. + format: uuid + type: string + type: object + type: array + serverGroup: + description: The server group to assign the machine to. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack server + group. If provided, it cannot be empty. + minProperties: 1 + properties: + name: + description: Name is the name of a server group to look for. + type: string + type: object + id: + description: ID is the ID of the server group to use. + format: uuid + type: string + type: object + serverMetadata: + description: Metadata mapping. Allows you to create a map of key value + pairs to add to the server instance. + items: + properties: + key: + description: Key is the server metadata key + maxLength: 255 + type: string + value: + description: Value is the server metadata value + maxLength: 255 + type: string + required: + - key + - value + type: object + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + sshKeyName: + description: The ssh key to inject in the instance + type: string + tags: + description: |- + Tags which will be added to the machine and all dependent resources + which support them. These are in addition to Tags defined on the + cluster. + Requires Nova api 2.52 minimum! items: type: string type: array @@ -1512,6 +2481,7 @@ spec: type: boolean required: - flavor + - image type: object status: description: OpenStackMachineStatus defines the observed state of OpenStackMachine. @@ -1542,37 +2512,37 @@ spec: operational state. properties: lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. format: date-time type: string message: - description: A human readable message indicating details about - the transition. This field may be empty. + description: |- + A human readable message indicating details about the transition. + This field may be empty. type: string reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. type: string severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. type: string status: description: Status of the condition, one of True, False, Unknown. type: string type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. type: string required: - lastTransitionTime @@ -1581,24 +2551,33 @@ spec: type: object type: array failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." + description: |- + FailureMessage will be set in the event that there is a terminal problem + reconciling the Machine and will contain a more verbose string suitable + for logging and human consumption. + + + This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over + time (like service outages), but instead indicate that something is + fundamentally wrong with the Machine's spec or the configuration of + the controller, and that manual intervention is required. Examples + of terminal errors would be invalid combinations of settings in the + spec, values that are unsupported by the controller, or the + responsible controller itself being critically misconfigured. + + + Any transient errors that occur during the reconciliation of Machines + can be added as events to the Machine object and/or logged in the + controller's output. type: string failureReason: description: MachineStatusError defines errors states for Machine objects. type: string + instanceID: + description: InstanceID is the OpenStack instance ID for this machine. + type: string instanceState: description: InstanceState is the state of the OpenStack instance for this machine. @@ -1606,6 +2585,206 @@ spec: ready: description: Ready is true when the provider resource is ready. type: boolean + resolved: + description: |- + Resolved contains parts of the machine spec with all external + references fully resolved. + properties: + imageID: + description: ImageID is the ID of the image to use for the machine + and is calculated based on ImageFilter. + type: string + ports: + description: Ports is the fully resolved list of ports to create + for the machine. + items: + description: ResolvedPortSpec is a PortOpts with all contained + references fully resolved. + properties: + adminStateUp: + description: AdminStateUp specifies whether the port should + be created in the up (true) or down (false) state. The + default is up. + type: boolean + allowedAddressPairs: + description: |- + AllowedAddressPairs is a list of address pairs which Neutron will + allow the port to send traffic from in addition to the port's + addresses. If not specified, the MAC Address will be the MAC Address + of the port. Depending on the configuration of Neutron, it may be + supported to specify a CIDR instead of a specific IP address. + items: + properties: + ipAddress: + description: |- + IPAddress is the IP address of the allowed address pair. Depending on + the configuration of Neutron, it may be supported to specify a CIDR + instead of a specific IP address. + type: string + macAddress: + description: |- + MACAddress is the MAC address of the allowed address pair. If not + specified, the MAC address will be the MAC address of the port. + type: string + required: + - ipAddress + type: object + type: array + description: + description: Description is a human-readable description + for the port. + type: string + disablePortSecurity: + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. + type: boolean + fixedIPs: + description: FixedIPs is a list of pairs of subnet and/or + IP address to assign to the port. If specified, these + must be subnets of the port's network. + items: + description: ResolvedFixedIP is a FixedIP with the Subnet + resolved to an ID. + properties: + ipAddress: + description: |- + IPAddress is a specific IP address to assign to the port. If SubnetID + is also specified, IPAddress must be a valid IP address in the + subnet. If Subnet is not specified, IPAddress must be a valid IP + address in any subnet of the port's network. + type: string + subnet: + description: SubnetID is the id of a subnet to create + the fixed IP of a port in. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + hostID: + description: HostID specifies the ID of the host where the + port resides. + type: string + macAddress: + description: MACAddress specifies the MAC address of the + port. If not specified, the MAC address will be generated. + type: string + name: + description: Name is the name of the port. + type: string + networkID: + description: NetworkID is the ID of the network the port + will be created in. + type: string + profile: + description: |- + Profile is a set of key-value pairs that are used for binding + details. We intentionally don't expose this as a map[string]string + because we only want to enable the users to set the values of the + keys that are known to work in OpenStack Networking API. See + https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + To set profiles, your tenant needs permissions rule:create_port, and + rule:create_port:binding:profile + properties: + ovsHWOffload: + description: OVSHWOffload enables or disables the OVS + hardware offload feature. + type: boolean + trustedVF: + description: TrustedVF enables or disables the “trusted + mode” for the VF. + type: boolean + type: object + propagateUplinkStatus: + description: PropageteUplinkStatus enables or disables the + propagate uplink status on the port. + type: boolean + securityGroups: + description: SecurityGroups is a list of security group + IDs to assign to the port. + items: + type: string + type: array + x-kubernetes-list-type: atomic + tags: + description: Tags applied to the port (and corresponding + trunk, if a trunk is configured.) + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: Trunk specifies whether trunking is enabled + at the port level. + type: boolean + valueSpecs: + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. + items: + description: ValueSpec represents a single value_spec + key-value pair. + properties: + key: + description: Key is the key in the key-value pair. + type: string + name: + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. + type: string + value: + description: Value is the value in the key-value pair. + type: string + required: + - key + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + vnicType: + description: |- + VNICType specifies the type of vNIC which this port should be + attached to. This is used to determine which mechanism driver(s) to + be used to bind the port. The valid values are normal, macvtap, + direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + remote-managed, although these values will not be validated in this + API to ensure compatibility with future neutron changes or custom + implementations. What type of vNIC is actually available depends on + deployments. If not specified, the Neutron default value is used. + type: string + required: + - description + - name + - networkID + type: object + type: array + serverGroupID: + description: ServerGroupID is the ID of the server group the machine + should be added to and is calculated based on ServerGroupFilter. + type: string + type: object + resources: + description: Resources contains references to OpenStack resources + created for the machine. + properties: + ports: + description: Ports is the status of the ports created for the + machine. + items: + properties: + id: + description: ID is the unique identifier of the port. + type: string + required: + - id + type: object + type: array + type: object type: object type: object served: true diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml index bc88d84fa2..7e5c5bbe6f 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: openstackmachinetemplates.infrastructure.cluster.x-k8s.io spec: group: infrastructure.cluster.x-k8s.io @@ -24,18 +24,26 @@ spec: name: v1alpha5 schema: openAPIV3Schema: - description: "OpenStackMachineTemplate is the Schema for the openstackmachinetemplates - API. \n Deprecated: This type will be removed in one of the next releases." + description: |- + OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -63,48 +71,48 @@ spec: server instance. type: string floatingIP: - description: The floatingIP which will be associated to the - machine, only used for master. The floatingIP should have - been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server - instance. If the RootVolume is specified, this will be ignored - and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server - instance. if it's empty, Image name will be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter when there - are multiple networks defined for the tenant. When you do - not specify both networks and ports parameters, the server - attaches to the only network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -165,26 +173,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must - also be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If specified - this will not be validated prior to server creation. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does not - already exist. When you do not specify both networks and - ports parameters, the server attaches to the only network - created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -201,10 +208,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -215,10 +221,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -262,9 +267,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -286,10 +291,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and receive - virtual network interface (VIF) port-specific information - to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -344,10 +349,9 @@ spec: type: string type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -438,7 +442,9 @@ spec: be marked as AccessIPv4 on the created compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -456,23 +462,34 @@ spec: - template type: object type: object - served: true + served: false storage: false - - name: v1alpha6 + - deprecated: true + deprecationWarning: The v1alpha6 version of OpenStackMachineTemplate has been + deprecated and will be removed in a future release of the API. Please upgrade. + name: v1alpha6 schema: openAPIV3Schema: - description: OpenStackMachineTemplate is the Schema for the openstackmachinetemplates - API. + description: |- + OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API. + + + Deprecated: This type will be removed in one of the next releases. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -500,48 +517,48 @@ spec: server instance. type: string floatingIP: - description: The floatingIP which will be associated to the - machine, only used for master. The floatingIP should have - been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: description: IdentityRef is a reference to a identity to be used when reconciling this cluster properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server - instance. If the RootVolume is specified, this will be ignored - and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server - instance. if it's empty, Image name will be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string networks: - description: A networks object. Required parameter when there - are multiple networks defined for the tenant. When you do - not specify both networks and ports parameters, the server - attaches to the only network created for the current tenant. + description: |- + A networks object. Required parameter when there are multiple networks defined for the tenant. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: filter: @@ -602,26 +619,25 @@ spec: type: string type: object uuid: - description: Optional UUID of the subnet. If specified - this will not be validated prior to server creation. - If specified, the enclosing `NetworkParam` must - also be specified by UUID. + description: |- + Optional UUID of the subnet. + If specified this will not be validated prior to server creation. + If specified, the enclosing `NetworkParam` must also be specified by UUID. type: string type: object type: array uuid: - description: Optional UUID of the network. If specified - this will not be validated prior to server creation. + description: |- + Optional UUID of the network. + If specified this will not be validated prior to server creation. Required if `Subnets` specifies a subnet by UUID. type: string type: object type: array ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does not - already exist. When you do not specify both networks and - ports parameters, the server attaches to the only network - created for the current tenant. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. items: properties: adminStateUp: @@ -638,10 +654,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -652,10 +667,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -699,9 +713,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -723,10 +737,10 @@ spec: profile: additionalProperties: type: string - description: A dictionary that enables the application - running on the specified host to pass and receive - virtual network interface (VIF) port-specific information - to the plug-in. + description: |- + A dictionary that enables the application running on the specified + host to pass and receive virtual network interface (VIF) port-specific + information to the plug-in. type: object projectId: type: string @@ -782,10 +796,9 @@ spec: type: array x-kubernetes-list-type: set tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -797,10 +810,10 @@ spec: If not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include - in the API request with OpenStack. This is an extension - point for the API, so what they do and if they are - supported, depends on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -809,9 +822,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the pair - and will not be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value @@ -907,7 +920,9 @@ spec: be marked as AccessIPv4 on the created compute instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! items: type: string type: array @@ -935,14 +950,19 @@ spec: API. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -966,12 +986,12 @@ spec: attach to the server. properties: name: - description: Name of the block device in the context - of a machine. If the block device is a volume, the - Cinder volume will be named as a combination of the - machine name and this name. Also, this name will be - used for tagging the block device. Information about - the block device tag can be obtained from the OpenStack + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack metadata API or the config drive. type: string sizeGiB: @@ -979,32 +999,32 @@ spec: in gibibytes (GiB). type: integer storage: - description: Storage specifies the storage type of the - block device and additional storage options. + description: |- + Storage specifies the storage type of the block device and + additional storage options. properties: type: - description: Type is the type of block device to - create. This can be either "Volume" or "Local". + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". type: string volume: description: Volume contains additional storage options for a volume block device. properties: availabilityZone: - description: AvailabilityZone is the volume - availability zone to create the volume in. - If omitted, the availability zone of the server - will be used. The availability zone must NOT - contain spaces otherwise it will lead to volume - that belongs to this availability zone register - failure, see kubernetes/cloud-provider-openstack#1379 - for further information. + description: |- + AvailabilityZone is the volume availability zone to create the volume in. + If omitted, the availability zone of the server will be used. + The availability zone must NOT contain spaces otherwise it will lead to volume that belongs + to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for + further information. type: string type: - description: Type is the Cinder volume type - of the volume. If omitted, the default Cinder - volume type that is configured in the OpenStack - cloud will be used. + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. type: string type: object required: @@ -1031,48 +1051,49 @@ spec: server instance. type: string floatingIP: - description: The floatingIP which will be associated to the - machine, only used for master. The floatingIP should have - been created and haven't been associated. + description: |- + The floatingIP which will be associated to the machine, only used for master. + The floatingIP should have been created and haven't been associated. type: string identityRef: - description: IdentityRef is a reference to a identity to be - used when reconciling this cluster + description: |- + IdentityRef is a reference to a identity to be used when reconciling this cluster. + If not specified, the identity ref of the cluster will be used instead. properties: kind: - description: Kind of the identity. Must be supported by - the infrastructure provider and may be either cluster - or namespace-scoped. + description: |- + Kind of the identity. Must be supported by the infrastructure + provider and may be either cluster or namespace-scoped. minLength: 1 type: string name: - description: Name of the infrastructure identity to be - used. Must be either a cluster-scoped resource, or namespaced-scoped - resource the same namespace as the resource(s) being - provisioned. + description: |- + Name of the infrastructure identity to be used. + Must be either a cluster-scoped resource, or namespaced-scoped + resource the same namespace as the resource(s) being provisioned. type: string required: - kind - name type: object image: - description: The name of the image to use for your server - instance. If the RootVolume is specified, this will be ignored - and use rootVolume directly. + description: |- + The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume directly. type: string imageUUID: - description: The uuid of the image to use for your server - instance. if it's empty, Image name will be used + description: |- + The uuid of the image to use for your server instance. + if it's empty, Image name will be used type: string instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string ports: - description: Ports to be attached to the server instance. - They are created if a port with the given name does not - already exist. If not specified a default port will be added - for the default cluster network. + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. items: properties: adminStateUp: @@ -1089,10 +1110,9 @@ spec: description: type: string disablePortSecurity: - description: DisablePortSecurity enables or disables - the port security when set. When not set, it takes - the value of the corresponding field at the network - level. + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. type: boolean fixedIPs: description: Specify pairs of subnet and/or IP address. @@ -1103,10 +1123,9 @@ spec: ipAddress: type: string subnet: - description: Subnet is an openstack subnet query - that will return the id of a subnet to create - the fixed IP of a port in. This query must not - return more than one subnet. + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. properties: cidr: type: string @@ -1150,9 +1169,9 @@ spec: in the list is used. type: string network: - description: Network is a query for an openstack network - that the port will be created or discovered on. This - will fail if the query returns more than one network. + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. properties: description: type: string @@ -1172,12 +1191,11 @@ spec: type: string type: object profile: - description: Profile is a set of key-value pairs that - are used for binding details. We intentionally don't - expose this as a map[string]string because we only - want to enable the users to set the values of the - keys that are known to work in OpenStack Networking - API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + description: |- + Profile is a set of key-value pairs that are used for binding details. + We intentionally don't expose this as a map[string]string because we only want to enable + the users to set the values of the keys that are known to work in OpenStack Networking API. + See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port properties: ovsHWOffload: description: OVSHWOffload enables or disables the @@ -1216,10 +1234,9 @@ spec: type: object type: array tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) These tags are applied - in addition to the instance's tags, which will also - be applied to the port. + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. items: type: string type: array @@ -1229,10 +1246,10 @@ spec: If not provided, openStackMachine.Spec.Trunk is inherited. type: boolean valueSpecs: - description: Value specs are extra parameters to include - in the API request with OpenStack. This is an extension - point for the API, so what they do and if they are - supported, depends on the specific OpenStack implementation. + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. items: description: ValueSpec represents a single value_spec key-value pair. @@ -1241,9 +1258,9 @@ spec: description: Key is the key in the key-value pair. type: string name: - description: Name is the name of the key-value - pair. This is just for identifying the pair - and will not be sent to the OpenStack API. + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. type: string value: description: Value is the value in the key-value @@ -1314,7 +1331,828 @@ spec: description: The ssh key to inject in the instance type: string tags: - description: Machine tags Requires Nova api 2.52 minimum! + description: |- + Machine tags + Requires Nova api 2.52 minimum! + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: Whether the server instance is created on a trunk + port or not. + type: boolean + required: + - flavor + type: object + required: + - spec + type: object + required: + - template + type: object + type: object + served: true + storage: false + - name: v1beta1 + schema: + openAPIV3Schema: + description: OpenStackMachineTemplate is the Schema for the openstackmachinetemplates + API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OpenStackMachineTemplateSpec defines the desired state of + OpenStackMachineTemplate. + properties: + template: + description: OpenStackMachineTemplateResource describes the data needed + to create a OpenStackMachine from a template. + properties: + spec: + description: Spec is the specification of the desired behavior + of the machine. + properties: + additionalBlockDevices: + description: AdditionalBlockDevices is a list of specifications + for additional block devices to attach to the server instance + items: + description: AdditionalBlockDevice is a block device to + attach to the server. + properties: + name: + description: |- + Name of the block device in the context of a machine. + If the block device is a volume, the Cinder volume will be named + as a combination of the machine name and this name. + Also, this name will be used for tagging the block device. + Information about the block device tag can be obtained from the OpenStack + metadata API or the config drive. + Name cannot be 'root', which is reserved for the root volume. + type: string + sizeGiB: + description: SizeGiB is the size of the block device + in gibibytes (GiB). + minimum: 1 + type: integer + storage: + description: |- + Storage specifies the storage type of the block device and + additional storage options. + properties: + type: + description: |- + Type is the type of block device to create. + This can be either "Volume" or "Local". + type: string + volume: + description: Volume contains additional storage + options for a volume block device. + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' + or default + rule: '!has(self.from) || self.from == ''Name'' + ? has(self.name) : !has(self.name)' + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + type: object + required: + - type + type: object + required: + - name + - sizeGiB + - storage + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + configDrive: + description: Config Drive support + type: boolean + flavor: + description: The flavor reference for the flavor for your + server instance. + type: string + floatingIPPoolRef: + description: |- + floatingIPPoolRef is a reference to a IPPool that will be assigned + to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP + will be assigned to the OpenStackMachine. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + identityRef: + description: |- + IdentityRef is a reference to a secret holding OpenStack credentials + to be used when reconciling this machine. If not specified, the + credentials specified in the cluster will be used. + properties: + cloudName: + description: CloudName specifies the name of the entry + in the clouds.yaml file to use. + type: string + name: + description: |- + Name is the name of a secret in the same namespace as the resource being provisioned. + The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. + The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. + type: string + required: + - cloudName + - name + type: object + image: + description: |- + The image to use for your server instance. + If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. If specified, + the combination of name and tags must return a single + matching image or an error will be raised. + type: string + tags: + description: The tags associated with the desired + image. If specified, the combination of name and + tags must return a single matching image or an error + will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the image. ID will not + be validated before use. + format: uuid + type: string + type: object + ports: + description: |- + Ports to be attached to the server instance. They are created if a port with the given name does not already exist. + If not specified a default port will be added for the default cluster network. + items: + properties: + adminStateUp: + description: AdminStateUp specifies whether the port + should be created in the up (true) or down (false) + state. The default is up. + type: boolean + allowedAddressPairs: + description: |- + AllowedAddressPairs is a list of address pairs which Neutron will + allow the port to send traffic from in addition to the port's + addresses. If not specified, the MAC Address will be the MAC Address + of the port. Depending on the configuration of Neutron, it may be + supported to specify a CIDR instead of a specific IP address. + items: + properties: + ipAddress: + description: |- + IPAddress is the IP address of the allowed address pair. Depending on + the configuration of Neutron, it may be supported to specify a CIDR + instead of a specific IP address. + type: string + macAddress: + description: |- + MACAddress is the MAC address of the allowed address pair. If not + specified, the MAC address will be the MAC address of the port. + type: string + required: + - ipAddress + type: object + type: array + description: + description: Description is a human-readable description + for the port. + type: string + disablePortSecurity: + description: |- + DisablePortSecurity enables or disables the port security when set. + When not set, it takes the value of the corresponding field at the network level. + type: boolean + fixedIPs: + description: FixedIPs is a list of pairs of subnet and/or + IP address to assign to the port. If specified, these + must be subnets of the port's network. + items: + properties: + ipAddress: + description: |- + IPAddress is a specific IP address to assign to the port. If Subnet + is also specified, IPAddress must be a valid IP address in the + subnet. If Subnet is not specified, IPAddress must be a valid IP + address in any subnet of the port's network. + type: string + subnet: + description: |- + Subnet is an openstack subnet query that will return the id of a subnet to create + the fixed IP of a port in. This query must not return more than one subnet. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to + select the subnet. It must match exactly + one subnet. + minProperties: 1 + properties: + cidr: + type: string + description: + type: string + gatewayIP: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RAMode: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the uuid of the subnet. + It will not be validated. + format: uuid + type: string + type: object + type: object + type: array + x-kubernetes-list-type: atomic + hostID: + description: HostID specifies the ID of the host where + the port resides. + type: string + macAddress: + description: MACAddress specifies the MAC address of + the port. If not specified, the MAC address will be + generated. + type: string + nameSuffix: + description: NameSuffix will be appended to the name + of the port if specified. If unspecified, instead + the 0-based index of the port in the list is used. + type: string + network: + description: |- + Network is a query for an openstack network that the port will be created or discovered on. + This will fail if the query returns more than one network. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a filter to select + an OpenStack network. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the network to use. + If ID is provided, the other filters cannot be + provided. Must be in UUID format. + format: uuid + type: string + type: object + profile: + description: |- + Profile is a set of key-value pairs that are used for binding + details. We intentionally don't expose this as a map[string]string + because we only want to enable the users to set the values of the + keys that are known to work in OpenStack Networking API. See + https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + To set profiles, your tenant needs permissions rule:create_port, and + rule:create_port:binding:profile + properties: + ovsHWOffload: + description: OVSHWOffload enables or disables the + OVS hardware offload feature. + type: boolean + trustedVF: + description: TrustedVF enables or disables the “trusted + mode” for the VF. + type: boolean + type: object + propagateUplinkStatus: + description: PropageteUplinkStatus enables or disables + the propagate uplink status on the port. + type: boolean + securityGroups: + description: SecurityGroups is a list of the names, + uuids, filters or any combination these of the security + groups to assign to the instance. + items: + description: SecurityGroupParam specifies an OpenStack + security group. It may be specified by ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select + an OpenStack security group. If provided, cannot + be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid + type: string + type: object + type: array + x-kubernetes-list-type: atomic + tags: + description: |- + Tags applied to the port (and corresponding trunk, if a trunk is configured.) + These tags are applied in addition to the instance's tags, which will also be applied to the port. + items: + type: string + type: array + x-kubernetes-list-type: set + trunk: + description: |- + Trunk specifies whether trunking is enabled at the port level. If not + provided the value is inherited from the machine, or false for a + bastion host. + type: boolean + valueSpecs: + description: |- + Value specs are extra parameters to include in the API request with OpenStack. + This is an extension point for the API, so what they do and if they are supported, + depends on the specific OpenStack implementation. + items: + description: ValueSpec represents a single value_spec + key-value pair. + properties: + key: + description: Key is the key in the key-value pair. + type: string + name: + description: |- + Name is the name of the key-value pair. + This is just for identifying the pair and will not be sent to the OpenStack API. + type: string + value: + description: Value is the value in the key-value + pair. + type: string + required: + - key + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + vnicType: + description: |- + VNICType specifies the type of vNIC which this port should be + attached to. This is used to determine which mechanism driver(s) to + be used to bind the port. The valid values are normal, macvtap, + direct, baremetal, direct-physical, virtio-forwarder, smart-nic and + remote-managed, although these values will not be validated in this + API to ensure compatibility with future neutron changes or custom + implementations. What type of vNIC is actually available depends on + deployments. If not specified, the Neutron default value is used. + type: string + type: object + type: array + providerID: + description: ProviderID is the unique identifier as specified + by the cloud provider. + type: string + rootVolume: + description: The volume metadata to boot from + properties: + availabilityZone: + description: |- + AvailabilityZone is the volume availability zone to create the volume + in. If not specified, the volume will be created without an explicit + availability zone. + properties: + from: + default: Name + description: |- + From specifies where we will obtain the availability zone for the + volume. The options are "Name" and "Machine". If "Name" is specified + then the Name field must also be specified. If "Machine" is specified + the volume will use the value of FailureDomain, if any, from the + associated Machine. + enum: + - Name + - Machine + type: string + name: + description: |- + Name is the name of a volume availability zone to use. It is required + if From is "Name". The volume availability zone name may not contain + spaces. + minLength: 1 + pattern: ^[^ ]+$ + type: string + type: object + x-kubernetes-validations: + - message: name is required when from is 'Name' or default + rule: '!has(self.from) || self.from == ''Name'' ? has(self.name) + : !has(self.name)' + sizeGiB: + description: SizeGiB is the size of the block device in + gibibytes (GiB). + minimum: 1 + type: integer + type: + description: |- + Type is the Cinder volume type of the volume. + If omitted, the default Cinder volume type that is configured in the OpenStack cloud + will be used. + type: string + required: + - sizeGiB + type: object + securityGroups: + description: The names of the security groups to assign to + the instance + items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object + id: + description: ID is the ID of the security group to use. + If ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid + type: string + type: object + type: array + serverGroup: + description: The server group to assign the machine to. + maxProperties: 1 + minProperties: 1 + properties: + filter: + description: Filter specifies a query to select an OpenStack + server group. If provided, it cannot be empty. + minProperties: 1 + properties: + name: + description: Name is the name of a server group to + look for. + type: string + type: object + id: + description: ID is the ID of the server group to use. + format: uuid + type: string + type: object + serverMetadata: + description: Metadata mapping. Allows you to create a map + of key value pairs to add to the server instance. + items: + properties: + key: + description: Key is the server metadata key + maxLength: 255 + type: string + value: + description: Value is the server metadata value + maxLength: 255 + type: string + required: + - key + - value + type: object + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + sshKeyName: + description: The ssh key to inject in the instance + type: string + tags: + description: |- + Tags which will be added to the machine and all dependent resources + which support them. These are in addition to Tags defined on the + cluster. + Requires Nova api 2.52 minimum! items: type: string type: array @@ -1325,6 +2163,7 @@ spec: type: boolean required: - flavor + - image type: object required: - spec diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index f26fa8c3b8..5e25640181 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -1,5 +1,5 @@ commonLabels: - cluster.x-k8s.io/v1beta1: v1alpha5_v1alpha6_v1alpha7 + cluster.x-k8s.io/v1beta1: v1alpha5_v1alpha6_v1alpha7_v1beta1 # This kustomization.yaml is not intended to be run by itself, # since it depends on service name and namespace that are out of this kustomize package. @@ -9,6 +9,7 @@ resources: - bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml - bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml - bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +- bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml # +kubebuilder:scaffold:crdkustomizeresource patches: @@ -18,6 +19,7 @@ patches: - path: patches/webhook_in_openstackmachines.yaml - path: patches/webhook_in_openstackmachinetemplates.yaml - path: patches/webhook_in_openstackclustertemplates.yaml +#- patches/webhook_in_openstackfloatingippools.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_openstackfloatingippools.yaml b/config/crd/patches/cainjection_in_openstackfloatingippools.yaml new file mode 100644 index 0000000000..edb01f4691 --- /dev/null +++ b/config/crd/patches/cainjection_in_openstackfloatingippools.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: openstackfloatingippools.infrastructure.cluster.x-k8s.io diff --git a/config/crd/patches/webhook_in_openstackfloatingippools.yaml b/config/crd/patches/webhook_in_openstackfloatingippools.yaml new file mode 100644 index 0000000000..abe4d216dc --- /dev/null +++ b/config/crd/patches/webhook_in_openstackfloatingippools.yaml @@ -0,0 +1,17 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: openstackfloatingippools.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhookClientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/config/default/namespace.yaml b/config/default/namespace.yaml index 1ab3a72555..7e4acaef06 100644 --- a/config/default/namespace.yaml +++ b/config/default/namespace.yaml @@ -2,3 +2,7 @@ apiVersion: v1 kind: Namespace metadata: name: system + labels: + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/warn: restricted + pod-security.kubernetes.io/audit: restricted diff --git a/config/rbac/openstackfloatingippool_editor_role.yaml b/config/rbac/openstackfloatingippool_editor_role.yaml new file mode 100644 index 0000000000..c126a23d4b --- /dev/null +++ b/config/rbac/openstackfloatingippool_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit openstackfloatingippools. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: openstackfloatingippool-editor-role +rules: +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackfloatingippools + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackfloatingippools/status + verbs: + - get diff --git a/config/rbac/openstackfloatingippool_viewer_role.yaml b/config/rbac/openstackfloatingippool_viewer_role.yaml new file mode 100644 index 0000000000..81cf2f1dbf --- /dev/null +++ b/config/rbac/openstackfloatingippool_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view openstackfloatingippools. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: openstackfloatingippool-viewer-role +rules: +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackfloatingippools + verbs: + - get + - list + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackfloatingippools/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 0eab520098..4790f87801 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -73,6 +73,26 @@ rules: - get - patch - update +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackfloatingippools + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackfloatingippools/status + verbs: + - get + - patch + - update - apiGroups: - infrastructure.cluster.x-k8s.io resources: @@ -93,3 +113,28 @@ rules: - get - patch - update +- apiGroups: + - ipam.cluster.x-k8s.io + resources: + - ipaddressclaims + - ipaddressclaims/status + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - ipam.cluster.x-k8s.io + resources: + - ipaddresses + - ipaddresses/status + verbs: + - create + - delete + - get + - list + - update + - watch diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index b2e5ad4c2b..032b3756be 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -1,74 +1,5 @@ --- apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - name: mutating-webhook-configuration -webhooks: -- admissionReviewVersions: - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackcluster - failurePolicy: Fail - matchPolicy: Equivalent - name: default.openstackcluster.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1alpha7 - operations: - - CREATE - - UPDATE - resources: - - openstackclusters - sideEffects: None -- admissionReviewVersions: - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackclustertemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: default.openstackclustertemplate.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1alpha7 - operations: - - CREATE - - UPDATE - resources: - - openstackclustertemplates - sideEffects: None -- admissionReviewVersions: - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachine - failurePolicy: Fail - matchPolicy: Equivalent - name: default.openstackmachine.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1alpha7 - operations: - - CREATE - - UPDATE - resources: - - openstackmachines - sideEffects: None ---- -apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: validating-webhook-configuration @@ -79,7 +10,7 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackcluster + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster failurePolicy: Fail matchPolicy: Equivalent name: validation.openstackcluster.infrastructure.cluster.x-k8s.io @@ -87,7 +18,7 @@ webhooks: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1alpha7 + - v1beta1 operations: - CREATE - UPDATE @@ -100,7 +31,7 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackclustertemplate + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate failurePolicy: Fail matchPolicy: Equivalent name: validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io @@ -108,7 +39,7 @@ webhooks: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1alpha7 + - v1beta1 operations: - CREATE - UPDATE @@ -121,7 +52,7 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachine + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine failurePolicy: Fail matchPolicy: Equivalent name: validation.openstackmachine.infrastructure.cluster.x-k8s.io @@ -129,7 +60,7 @@ webhooks: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1alpha7 + - v1beta1 operations: - CREATE - UPDATE @@ -142,7 +73,7 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachinetemplate + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachinetemplate failurePolicy: Fail matchPolicy: Equivalent name: validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io @@ -150,7 +81,7 @@ webhooks: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1alpha7 + - v1beta1 operations: - CREATE - UPDATE diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go index 08177fc9ed..d310aced6a 100644 --- a/controllers/openstackcluster_controller.go +++ b/controllers/openstackcluster_controller.go @@ -20,13 +20,16 @@ import ( "context" "errors" "fmt" - "reflect" "time" + "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" + "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + kerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/tools/record" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" capierrors "sigs.k8s.io/cluster-api/errors" "sigs.k8s.io/cluster-api/util" @@ -39,16 +42,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/loadbalancer" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking" "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope" + utils "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/controllers" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names" ) const ( @@ -68,7 +71,7 @@ type OpenStackClusterReconciler struct { // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters/status,verbs=get;update;patch // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch -func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { +func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, reterr error) { log := ctrl.LoggerFrom(ctx) // Fetch the OpenStackCluster instance @@ -107,16 +110,16 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req // Always patch the openStackCluster when exiting this function so we can persist any OpenStackCluster changes. defer func() { if err := patchHelper.Patch(ctx, openStackCluster); err != nil { - if reterr == nil { - reterr = fmt.Errorf("error patching OpenStackCluster %s/%s: %w", openStackCluster.Namespace, openStackCluster.Name, err) - } + result = ctrl.Result{} + reterr = kerrors.NewAggregate([]error{reterr, fmt.Errorf("error patching OpenStackCluster %s/%s: %w", openStackCluster.Namespace, openStackCluster.Name, err)}) } }() - scope, err := r.ScopeFactory.NewClientScopeFromCluster(ctx, r.Client, openStackCluster, r.CaCertificates, log) + clientScope, err := r.ScopeFactory.NewClientScopeFromCluster(ctx, r.Client, openStackCluster, r.CaCertificates, log) if err != nil { return reconcile.Result{}, err } + scope := scope.NewWithLogger(clientScope, log) // Handle deleted clusters if !openStackCluster.DeletionTimestamp.IsZero() { @@ -127,7 +130,7 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req return reconcileNormal(scope, cluster, openStackCluster) } -func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) { +func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) { scope.Logger().Info("Reconciling Cluster delete") // Wait for machines to be deleted before removing the finalizer as they @@ -144,8 +147,19 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope return ctrl.Result{RequeueAfter: 5 * time.Second}, nil } - if err := deleteBastion(scope, cluster, openStackCluster); err != nil { - return reconcile.Result{}, err + clusterResourceName := names.ClusterResourceName(cluster) + + // A bastion may have been created if cluster initialisation previously reached populating the network status + // We attempt to delete it even if no status was written, just in case + if openStackCluster.Status.Network != nil { + // Attempt to resolve bastion resources before delete. We don't need to worry about starting if the resources have changed on update. + if _, err := resolveBastionResources(scope, clusterResourceName, openStackCluster); err != nil { + return reconcile.Result{}, err + } + + if err := deleteBastion(scope, cluster, openStackCluster); err != nil { + return reconcile.Result{}, err + } } networkingService, err := networking.NewService(scope) @@ -153,43 +167,41 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope return reconcile.Result{}, err } - clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name) - - if openStackCluster.Spec.APIServerLoadBalancer.Enabled { + if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() { loadBalancerService, err := loadbalancer.NewService(scope) if err != nil { return reconcile.Result{}, err } - if err = loadBalancerService.DeleteLoadBalancer(openStackCluster, clusterName); err != nil { + if err = loadBalancerService.DeleteLoadBalancer(openStackCluster, clusterResourceName); err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete load balancer: %w", err)) return reconcile.Result{}, fmt.Errorf("failed to delete load balancer: %w", err) } } - if err = networkingService.DeleteSecurityGroups(openStackCluster, clusterName); err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete security groups: %w", err)) - return reconcile.Result{}, fmt.Errorf("failed to delete security groups: %w", err) - } - - // if NodeCIDR was not set, no network was created. - if openStackCluster.Spec.NodeCIDR != "" { - if err = networkingService.DeleteRouter(openStackCluster, clusterName); err != nil { + // if ManagedSubnets was not set, no network was created. + if len(openStackCluster.Spec.ManagedSubnets) > 0 { + if err = networkingService.DeleteRouter(openStackCluster, clusterResourceName); err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete router: %w", err)) return ctrl.Result{}, fmt.Errorf("failed to delete router: %w", err) } - if err = networkingService.DeletePorts(openStackCluster); err != nil { + if err = networkingService.DeleteClusterPorts(openStackCluster); err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete ports: %w", err)) return reconcile.Result{}, fmt.Errorf("failed to delete ports: %w", err) } - if err = networkingService.DeleteNetwork(openStackCluster, clusterName); err != nil { + if err = networkingService.DeleteNetwork(openStackCluster, clusterResourceName); err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete network: %w", err)) return ctrl.Result{}, fmt.Errorf("failed to delete network: %w", err) } } + if err = networkingService.DeleteSecurityGroups(openStackCluster, clusterResourceName); err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete security groups: %w", err)) + return reconcile.Result{}, fmt.Errorf("failed to delete security groups: %w", err) + } + // Cluster is deleted so remove the finalizer. controllerutil.RemoveFinalizer(openStackCluster, infrav1.ClusterFinalizer) scope.Logger().Info("Reconciled Cluster deleted successfully") @@ -205,7 +217,48 @@ func contains(arr []string, target string) bool { return false } -func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error { +func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) { + // Resolve and store resources for the bastion + if openStackCluster.Spec.Bastion.IsEnabled() { + if openStackCluster.Status.Bastion == nil { + openStackCluster.Status.Bastion = &infrav1.BastionStatus{} + } + if openStackCluster.Spec.Bastion.Spec == nil { + return false, fmt.Errorf("bastion spec is nil when bastion is enabled, this shouldn't happen") + } + resolved := openStackCluster.Status.Bastion.Resolved + if resolved == nil { + resolved = &infrav1.ResolvedMachineSpec{} + openStackCluster.Status.Bastion.Resolved = resolved + } + changed, err := compute.ResolveMachineSpec(scope, + openStackCluster.Spec.Bastion.Spec, resolved, + clusterResourceName, bastionName(clusterResourceName), + openStackCluster, getBastionSecurityGroupID(openStackCluster)) + if err != nil { + return false, err + } + if changed { + // If the resolved machine spec changed we need to restart the reconcile to avoid inconsistencies between reconciles. + return true, nil + } + resources := openStackCluster.Status.Bastion.Resources + if resources == nil { + resources = &infrav1.MachineResources{} + openStackCluster.Status.Bastion.Resources = resources + } + + err = compute.AdoptMachineResources(scope, resolved, resources) + if err != nil { + return false, err + } + } + return false, nil +} + +func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error { + scope.Logger().Info("Deleting Bastion") + computeService, err := compute.NewService(scope) if err != nil { return err @@ -215,13 +268,38 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust return err } - instanceName := fmt.Sprintf("%s-bastion", cluster.Name) - instanceStatus, err := computeService.GetInstanceStatusByName(openStackCluster, instanceName) - if err != nil { - return err + if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.FloatingIP != "" { + if err = networkingService.DeleteFloatingIP(openStackCluster, openStackCluster.Status.Bastion.FloatingIP); err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete floating IP: %w", err)) + return fmt.Errorf("failed to delete floating IP: %w", err) + } + } + + bastionStatus := openStackCluster.Status.Bastion + + var instanceStatus *compute.InstanceStatus + if bastionStatus != nil && bastionStatus.ID != "" { + instanceStatus, err = computeService.GetInstanceStatus(openStackCluster.Status.Bastion.ID) + if err != nil { + return err + } + } else { + instanceStatus, err = computeService.GetInstanceStatusByName(openStackCluster, bastionName(cluster.Name)) + if err != nil { + return err + } } - if instanceStatus != nil { + // If no instance was created we currently need to check for orphaned + // volumes. + if instanceStatus == nil { + bastion := openStackCluster.Spec.Bastion + if bastion != nil && bastion.Spec != nil { + if err := computeService.DeleteVolumes(bastionName(cluster.Name), bastion.Spec.RootVolume, bastion.Spec.AdditionalBlockDevices); err != nil { + return fmt.Errorf("delete volumes: %w", err) + } + } + } else { instanceNS, err := instanceStatus.NetworkStatus() if err != nil { return err @@ -230,6 +308,7 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust for _, address := range addresses { if address.Type == corev1.NodeExternalIP { + // Floating IP may not have properly saved in bastion status (thus not deleted above), delete any remaining floating IP if err = networkingService.DeleteFloatingIP(openStackCluster, address.Address); err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete floating IP: %w", err)) return fmt.Errorf("failed to delete floating IP: %w", err) @@ -237,28 +316,35 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust } } - instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name) - - if err = computeService.DeleteInstance(openStackCluster, openStackCluster, instanceStatus, instanceSpec); err != nil { + if err = computeService.DeleteInstance(openStackCluster, instanceStatus); err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete bastion: %w", err)) return fmt.Errorf("failed to delete bastion: %w", err) } } - openStackCluster.Status.Bastion = nil - - if err = networkingService.DeleteBastionSecurityGroup(openStackCluster, fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)); err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete bastion security group: %w", err)) - return fmt.Errorf("failed to delete bastion security group: %w", err) + if bastionStatus != nil && bastionStatus.Resources != nil { + trunkSupported, err := networkingService.IsTrunkExtSupported() + if err != nil { + return err + } + for _, port := range bastionStatus.Resources.Ports { + if err := networkingService.DeleteInstanceTrunkAndPort(openStackCluster, port, trunkSupported); err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete port: %w", err)) + return fmt.Errorf("failed to delete port: %w", err) + } + } + bastionStatus.Resources.Ports = nil } - openStackCluster.Status.BastionSecurityGroup = nil + scope.Logger().Info("Deleted Bastion") + + openStackCluster.Status.Bastion = nil delete(openStackCluster.ObjectMeta.Annotations, BastionInstanceHashAnnotation) return nil } -func reconcileNormal(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) { //nolint:unparam +func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) { //nolint:unparam scope.Logger().Info("Reconciling Cluster") // If the OpenStackCluster doesn't have our finalizer, add it. @@ -277,9 +363,13 @@ func reconcileNormal(scope scope.Scope, cluster *clusterv1.Cluster, openStackClu return reconcile.Result{}, err } - if err = reconcileBastion(scope, cluster, openStackCluster); err != nil { + result, err := reconcileBastion(scope, cluster, openStackCluster) + if err != nil { return reconcile.Result{}, err } + if result != nil { + return *result, nil + } availabilityZones, err := computeService.GetAvailabilityZones() if err != nil { @@ -290,7 +380,7 @@ func reconcileNormal(scope scope.Scope, cluster *clusterv1.Cluster, openStackClu openStackCluster.Status.FailureDomains = make(clusterv1.FailureDomains) for _, az := range availabilityZones { // By default, the AZ is used or not used for control plane nodes depending on the flag - found := !openStackCluster.Spec.ControlPlaneOmitAvailabilityZone + found := !ptr.Deref(openStackCluster.Spec.ControlPlaneOmitAvailabilityZone, false) // If explicit AZs for control plane nodes are given, they override the value if len(openStackCluster.Spec.ControlPlaneAvailabilityZones) > 0 { found = contains(openStackCluster.Spec.ControlPlaneAvailabilityZones, az.ZoneName) @@ -308,108 +398,221 @@ func reconcileNormal(scope scope.Scope, cluster *clusterv1.Cluster, openStackClu return reconcile.Result{}, nil } -func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error { - scope.Logger().Info("Reconciling Bastion") +func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (*ctrl.Result, error) { + scope.Logger().V(4).Info("Reconciling Bastion") - if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled { - return deleteBastion(scope, cluster, openStackCluster) + clusterResourceName := names.ClusterResourceName(cluster) + changed, err := resolveBastionResources(scope, clusterResourceName, openStackCluster) + if err != nil { + return nil, err + } + if changed { + return &reconcile.Result{}, nil + } + + // No Bastion defined + if !openStackCluster.Spec.Bastion.IsEnabled() { + // Delete any existing bastion + if openStackCluster.Status.Bastion != nil { + if err := deleteBastion(scope, cluster, openStackCluster); err != nil { + return nil, err + } + // Reconcile again before continuing + return &reconcile.Result{}, nil + } + + // Otherwise nothing to do + return nil, nil } computeService, err := compute.NewService(scope) if err != nil { - return err + return nil, err } - instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name) - bastionHash, err := compute.HashInstanceSpec(instanceSpec) + networkingService, err := networking.NewService(scope) if err != nil { - return fmt.Errorf("failed computing bastion hash from instance spec: %w", err) + return nil, err } - instanceStatus, err := computeService.GetInstanceStatusByName(openStackCluster, fmt.Sprintf("%s-bastion", cluster.Name)) + instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster) if err != nil { - return err + return nil, err } - if instanceStatus != nil { - if !bastionHashHasChanged(bastionHash, openStackCluster.ObjectMeta.Annotations) { - bastion, err := instanceStatus.BastionStatus(openStackCluster) - if err != nil { - return err - } - // Add the current hash if no annotation is set. - if _, ok := openStackCluster.ObjectMeta.Annotations[BastionInstanceHashAnnotation]; !ok { - annotations.AddAnnotations(openStackCluster, map[string]string{BastionInstanceHashAnnotation: bastionHash}) - } - openStackCluster.Status.Bastion = bastion - return nil - } + + bastionHash, err := compute.HashInstanceSpec(instanceSpec) + if err != nil { + return nil, fmt.Errorf("failed computing bastion hash from instance spec: %w", err) + } + if bastionHashHasChanged(bastionHash, openStackCluster.ObjectMeta.Annotations) { + scope.Logger().Info("Bastion instance spec has changed, deleting existing bastion") if err := deleteBastion(scope, cluster, openStackCluster); err != nil { - return err + return nil, err } + + // Add the new annotation and reconcile again before continuing + annotations.AddAnnotations(openStackCluster, map[string]string{BastionInstanceHashAnnotation: bastionHash}) + return &reconcile.Result{}, nil } - instanceStatus, err = computeService.CreateInstance(openStackCluster, openStackCluster, instanceSpec, cluster.Name) + err = getOrCreateBastionPorts(openStackCluster, networkingService) if err != nil { - return fmt.Errorf("failed to reconcile bastion: %w", err) + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create ports for bastion: %w", err)) + return nil, fmt.Errorf("failed to get or create ports for bastion: %w", err) } + bastionPortIDs := GetPortIDs(openStackCluster.Status.Bastion.Resources.Ports) - networkingService, err := networking.NewService(scope) - if err != nil { - return err + var instanceStatus *compute.InstanceStatus + if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.ID != "" { + if instanceStatus, err = computeService.GetInstanceStatus(openStackCluster.Status.Bastion.ID); err != nil { + return nil, err + } } - clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name) - fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, openStackCluster.Spec.Bastion.Instance.FloatingIP) - if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create floating IP for bastion: %w", err)) - return fmt.Errorf("failed to get or create floating IP for bastion: %w", err) + if instanceStatus == nil { + // Check if there is an existing instance with bastion name, in case where bastion ID would not have been properly stored in cluster status + if instanceStatus, err = computeService.GetInstanceStatusByName(openStackCluster, instanceSpec.Name); err != nil { + return nil, err + } } + if instanceStatus == nil { + instanceStatus, err = computeService.CreateInstance(openStackCluster, instanceSpec, bastionPortIDs) + if err != nil { + return nil, fmt.Errorf("failed to create bastion: %w", err) + } + } + + // Save hash & status as soon as we know we have an instance + instanceStatus.UpdateBastionStatus(openStackCluster) + + // Make sure that bastion instance has a valid state + switch instanceStatus.State() { + case infrav1.InstanceStateError: + return nil, fmt.Errorf("failed to reconcile bastion, instance state is ERROR") + case infrav1.InstanceStateBuild, infrav1.InstanceStateUndefined: + scope.Logger().Info("Waiting for bastion instance to become ACTIVE", "id", instanceStatus.ID(), "status", instanceStatus.State()) + return &reconcile.Result{RequeueAfter: waitForBuildingInstanceToReconcile}, nil + case infrav1.InstanceStateDeleted: + // Not clear why this would happen, so try to clean everything up before reconciling again + if err := deleteBastion(scope, cluster, openStackCluster); err != nil { + return nil, err + } + return &reconcile.Result{}, nil + } + port, err := computeService.GetManagementPort(openStackCluster, instanceStatus) if err != nil { err = fmt.Errorf("getting management port for bastion: %w", err) handleUpdateOSCError(openStackCluster, err) - return err + return nil, err + } + + return bastionAddFloatingIP(openStackCluster, clusterResourceName, port, networkingService) +} + +func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string, port *ports.Port, networkingService *networking.Service) (*reconcile.Result, error) { + fp, err := networkingService.GetFloatingIPByPortID(port.ID) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create floating IP for bastion: %w", err)) + return nil, fmt.Errorf("failed to get floating IP for bastion port: %w", err) + } + if fp != nil { + // Floating IP is already attached to bastion, no need to proceed + openStackCluster.Status.Bastion.FloatingIP = fp.FloatingIP + return nil, nil + } + + var floatingIP *string + switch { + case openStackCluster.Status.Bastion.FloatingIP != "": + // Some floating IP has already been created for this bastion, make sure we re-use it + floatingIP = &openStackCluster.Status.Bastion.FloatingIP + case openStackCluster.Spec.Bastion.FloatingIP != nil: + // Use floating IP from the spec + floatingIP = openStackCluster.Spec.Bastion.FloatingIP + } + // Check if there is an existing floating IP attached to bastion, in case where FloatingIP would not yet have been stored in cluster status + fp, err = networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterResourceName, floatingIP) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create floating IP for bastion: %w", err)) + return nil, fmt.Errorf("failed to get or create floating IP for bastion: %w", err) } + openStackCluster.Status.Bastion.FloatingIP = fp.FloatingIP + err = networkingService.AssociateFloatingIP(openStackCluster, fp, port.ID) if err != nil { handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to associate floating IP with bastion: %w", err)) - return fmt.Errorf("failed to associate floating IP with bastion: %w", err) + return nil, fmt.Errorf("failed to associate floating IP with bastion: %w", err) } - bastion, err := instanceStatus.BastionStatus(openStackCluster) - if err != nil { - return err + return nil, nil +} + +func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) { + bastion := openStackCluster.Spec.Bastion + if bastion == nil { + bastion = &infrav1.Bastion{} + } + if bastion.Spec == nil { + // For the case when Bastion is deleted but we don't have spec, let's use an empty one. + // v1beta1 API validations prevent this from happening in normal circumstances. + bastion.Spec = &infrav1.OpenStackMachineSpec{} + } + resolved := openStackCluster.Status.Bastion.Resolved + if resolved == nil { + return nil, errors.New("bastion resolved is nil") + } + + machineSpec := bastion.Spec + instanceSpec := &compute.InstanceSpec{ + Name: bastionName(cluster.Name), + Flavor: machineSpec.Flavor, + SSHKeyName: machineSpec.SSHKeyName, + ImageID: resolved.ImageID, + RootVolume: machineSpec.RootVolume, + ServerGroupID: resolved.ServerGroupID, + Tags: compute.InstanceTags(machineSpec, openStackCluster), + } + if bastion.AvailabilityZone != nil { + instanceSpec.FailureDomain = *bastion.AvailabilityZone + } + return instanceSpec, nil +} + +func bastionName(clusterResourceName string) string { + return fmt.Sprintf("%s-bastion", clusterResourceName) +} + +// getBastionSecurityGroupID returns the ID of the bastion security group if +// managed security groups is enabled. +func getBastionSecurityGroupID(openStackCluster *infrav1.OpenStackCluster) *string { + if openStackCluster.Spec.ManagedSecurityGroups == nil { + return nil + } + + if openStackCluster.Status.BastionSecurityGroup != nil { + return &openStackCluster.Status.BastionSecurityGroup.ID } - bastion.FloatingIP = fp.FloatingIP - openStackCluster.Status.Bastion = bastion - annotations.AddAnnotations(openStackCluster, map[string]string{BastionInstanceHashAnnotation: bastionHash}) return nil } -func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) *compute.InstanceSpec { - name := fmt.Sprintf("%s-bastion", clusterName) - instanceSpec := &compute.InstanceSpec{ - Name: name, - Flavor: openStackCluster.Spec.Bastion.Instance.Flavor, - SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName, - Image: openStackCluster.Spec.Bastion.Instance.Image, - ImageUUID: openStackCluster.Spec.Bastion.Instance.ImageUUID, - FailureDomain: openStackCluster.Spec.Bastion.AvailabilityZone, - RootVolume: openStackCluster.Spec.Bastion.Instance.RootVolume, +func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error { + desiredPorts := openStackCluster.Status.Bastion.Resolved.Ports + resources := openStackCluster.Status.Bastion.Resources + if resources == nil { + return errors.New("bastion resources are nil") } - instanceSpec.SecurityGroups = openStackCluster.Spec.Bastion.Instance.SecurityGroups - if openStackCluster.Spec.ManagedSecurityGroups { - if openStackCluster.Status.BastionSecurityGroup != nil { - instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{ - ID: openStackCluster.Status.BastionSecurityGroup.ID, - }) - } + if len(desiredPorts) == len(resources.Ports) { + return nil } - instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports + err := networkingService.CreatePorts(openStackCluster, desiredPorts, resources) + if err != nil { + return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err) + } - return instanceSpec + return nil } // bastionHashHasChanged returns a boolean whether if the latest bastion hash, built from the instance spec, has changed or not. @@ -421,8 +624,59 @@ func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]str return latestHash != computeHash } -func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error { - clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name) +func resolveLoadBalancerNetwork(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error { + lbSpec := openStackCluster.Spec.APIServerLoadBalancer + if lbSpec.IsEnabled() { + lbStatus := openStackCluster.Status.APIServerLoadBalancer + if lbStatus == nil { + lbStatus = &infrav1.LoadBalancer{} + openStackCluster.Status.APIServerLoadBalancer = lbStatus + } + + lbNetStatus := lbStatus.LoadBalancerNetwork + if lbNetStatus == nil { + lbNetStatus = &infrav1.NetworkStatusWithSubnets{ + NetworkStatus: infrav1.NetworkStatus{}, + } + } + + if lbSpec.Network != nil { + lbNet, err := networkingService.GetNetworkByParam(lbSpec.Network) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find loadbalancer network: %w", err)) + return fmt.Errorf("failed to find network: %w", err) + } + + lbNetStatus.Name = lbNet.Name + lbNetStatus.ID = lbNet.ID + lbNetStatus.Tags = lbNet.Tags + + // Filter out only relevant subnets specified by the spec + lbNetStatus.Subnets = []infrav1.Subnet{} + for _, s := range lbSpec.Subnets { + matchFound := false + for _, subnetID := range lbNet.Subnets { + if s.ID != nil && subnetID == *s.ID { + matchFound = true + lbNetStatus.Subnets = append( + lbNetStatus.Subnets, infrav1.Subnet{ + ID: *s.ID, + }) + } + } + if !matchFound { + handleUpdateOSCError(openStackCluster, fmt.Errorf("no subnet match was found in the specified network (specified subnet: %v, available subnets: %v)", s, lbNet.Subnets)) + return fmt.Errorf("no subnet match was found in the specified network (specified subnet: %v, available subnets: %v)", s, lbNet.Subnets) + } + } + } + } + + return nil +} + +func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error { + clusterResourceName := names.ClusterResourceName(cluster) networkingService, err := networking.NewService(scope) if err != nil { @@ -437,92 +691,128 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o return fmt.Errorf("failed to reconcile external network: %w", err) } - if openStackCluster.Spec.NodeCIDR == "" { - scope.Logger().V(4).Info("No need to reconcile network, searching network and subnet instead") - - netOpts := openStackCluster.Spec.Network.ToListOpt() - networkList, err := networkingService.GetNetworksByFilter(&netOpts) - if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find network: %w", err)) - return fmt.Errorf("failed to find network: %w", err) - } - if len(networkList) == 0 { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find any network")) - return fmt.Errorf("failed to find any network") - } - if len(networkList) > 1 { - handleUpdateOSCError(openStackCluster, fmt.Errorf("found multiple networks (result: %v)", networkList)) - return fmt.Errorf("found multiple networks (result: %v)", networkList) + if len(openStackCluster.Spec.ManagedSubnets) == 0 { + if err := reconcilePreExistingNetworkComponents(scope, networkingService, openStackCluster); err != nil { + return err } - if openStackCluster.Status.Network == nil { - openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{} + } else if len(openStackCluster.Spec.ManagedSubnets) == 1 { + if err := reconcileProvisionedNetworkComponents(networkingService, openStackCluster, clusterResourceName); err != nil { + return err } - openStackCluster.Status.Network.ID = networkList[0].ID - openStackCluster.Status.Network.Name = networkList[0].Name - openStackCluster.Status.Network.Tags = networkList[0].Tags + } else { + return fmt.Errorf("failed to reconcile network: ManagedSubnets only supports one element, %d provided", len(openStackCluster.Spec.ManagedSubnets)) + } - subnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &openStackCluster.Spec.Subnet) - if err != nil { - err = fmt.Errorf("failed to find subnet: %w", err) + err = resolveLoadBalancerNetwork(openStackCluster, networkingService) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile loadbalancer network: %w", err)) + return fmt.Errorf("failed to reconcile loadbalancer network: %w", err) + } - // Set the cluster to failed if subnet filter is invalid - if errors.Is(err, networking.ErrFilterMatch) { - handleUpdateOSCError(openStackCluster, err) - } + err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterResourceName) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile security groups: %w", err)) + return fmt.Errorf("failed to reconcile security groups: %w", err) + } - return err - } + return reconcileControlPlaneEndpoint(scope, networkingService, openStackCluster, clusterResourceName) +} - openStackCluster.Status.Network.Subnets = []infrav1.Subnet{ - { - ID: subnet.ID, - Name: subnet.Name, - CIDR: subnet.CIDR, - Tags: subnet.Tags, - }, - } - } else { - err := networkingService.ReconcileNetwork(openStackCluster, clusterName) +// reconcilePreExistingNetworkComponents reconciles the cluster network status when the cluster is +// using pre-existing networks and subnets which are not provisioned by the +// cluster controller. +func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) error { + scope.Logger().V(4).Info("No need to reconcile network, searching network and subnet instead") + + if openStackCluster.Status.Network == nil { + openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{} + } + + if openStackCluster.Spec.Network != nil { + network, err := networkingService.GetNetworkByParam(openStackCluster.Spec.Network) if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile network: %w", err)) - return fmt.Errorf("failed to reconcile network: %w", err) + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find network: %w", err)) + return fmt.Errorf("error fetching cluster network: %w", err) } - err = networkingService.ReconcileSubnet(openStackCluster, clusterName) - if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile subnets: %w", err)) - return fmt.Errorf("failed to reconcile subnets: %w", err) + setClusterNetwork(openStackCluster, network) + } + + subnets, err := getClusterSubnets(networkingService, openStackCluster) + if err != nil { + return err + } + + // Populate the cluster status with the cluster subnets + capoSubnets := make([]infrav1.Subnet, len(subnets)) + for i := range subnets { + subnet := &subnets[i] + capoSubnets[i] = infrav1.Subnet{ + ID: subnet.ID, + Name: subnet.Name, + CIDR: subnet.CIDR, + Tags: subnet.Tags, } - err = networkingService.ReconcileRouter(openStackCluster, clusterName) + } + if err := utils.ValidateSubnets(capoSubnets); err != nil { + return err + } + openStackCluster.Status.Network.Subnets = capoSubnets + + // If network is not yet populated, use networkID defined on the first + // cluster subnet to get the Network. Cluster subnets are constrained to + // be in the same network. + if openStackCluster.Status.Network.ID == "" && len(subnets) > 0 { + network, err := networkingService.GetNetworkByID(subnets[0].NetworkID) if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile router: %w", err)) - return fmt.Errorf("failed to reconcile router: %w", err) + return err } + setClusterNetwork(openStackCluster, network) } - err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterName) + return nil +} + +func reconcileProvisionedNetworkComponents(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error { + err := networkingService.ReconcileNetwork(openStackCluster, clusterResourceName) if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile security groups: %w", err)) - return fmt.Errorf("failed to reconcile security groups: %w", err) + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile network: %w", err)) + return fmt.Errorf("failed to reconcile network: %w", err) + } + err = networkingService.ReconcileSubnet(openStackCluster, clusterResourceName) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile subnets: %w", err)) + return fmt.Errorf("failed to reconcile subnets: %w", err) + } + err = networkingService.ReconcileRouter(openStackCluster, clusterResourceName) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile router: %w", err)) + return fmt.Errorf("failed to reconcile router: %w", err) } + return nil +} + +// reconcileControlPlaneEndpoint configures the control plane endpoint for the +// cluster, creating it if necessary, and updates ControlPlaneEndpoint in the +// cluster spec. +func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error { // Calculate the port that we will use for the API server - var apiServerPort int - switch { - case openStackCluster.Spec.ControlPlaneEndpoint.IsValid(): - apiServerPort = int(openStackCluster.Spec.ControlPlaneEndpoint.Port) - case openStackCluster.Spec.APIServerPort != 0: - apiServerPort = openStackCluster.Spec.APIServerPort - default: - apiServerPort = 6443 - } + apiServerPort := getAPIServerPort(openStackCluster) + + // host must be set by a matching control plane endpoint provider below + var host string - if openStackCluster.Spec.APIServerLoadBalancer.Enabled { + switch { + // API server load balancer is enabled. Create an Octavia load balancer. + // Note that we reconcile the load balancer even if the control plane + // endpoint is already set. + case openStackCluster.Spec.APIServerLoadBalancer.IsEnabled(): loadBalancerService, err := loadbalancer.NewService(scope) if err != nil { return err } - terminalFailure, err := loadBalancerService.ReconcileLoadBalancer(openStackCluster, clusterName, apiServerPort) + terminalFailure, err := loadBalancerService.ReconcileLoadBalancer(openStackCluster, clusterResourceName, apiServerPort) if err != nil { // if it's terminalFailure (not Transient), set the Failure reason and message if terminalFailure { @@ -530,71 +820,70 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o } return fmt.Errorf("failed to reconcile load balancer: %w", err) } - } - if !openStackCluster.Spec.ControlPlaneEndpoint.IsValid() { - var host string - // If there is a load balancer use the floating IP for it if set, falling back to the internal IP - switch { - case openStackCluster.Spec.APIServerLoadBalancer.Enabled: - if openStackCluster.Status.APIServerLoadBalancer.IP != "" { - host = openStackCluster.Status.APIServerLoadBalancer.IP - } else { - host = openStackCluster.Status.APIServerLoadBalancer.InternalIP - } - case !openStackCluster.Spec.DisableAPIServerFloatingIP: - // If floating IPs are not disabled, get one to use as the VIP for the control plane - fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, openStackCluster.Spec.APIServerFloatingIP) - if err != nil { - handleUpdateOSCError(openStackCluster, fmt.Errorf("floating IP cannot be got or created: %w", err)) - return fmt.Errorf("floating IP cannot be got or created: %w", err) - } - host = fp.FloatingIP - case openStackCluster.Spec.APIServerFixedIP != "": - // If a fixed IP was specified, assume that the user is providing the extra configuration - // to use that IP as the VIP for the API server, e.g. using keepalived or kube-vip - host = openStackCluster.Spec.APIServerFixedIP - default: - // For now, we do not provide a managed VIP without either a load balancer or a floating IP - // In the future, we could manage a VIP port on the cluster network and set allowedAddressPairs - // accordingly when creating control plane machines - // However this would require us to deploy software on the control plane hosts to manage the - // VIP (e.g. keepalived/kube-vip) - return fmt.Errorf("unable to determine VIP for API server") + // Control plane endpoint is the floating IP if one was defined, otherwise the VIP address + if openStackCluster.Status.APIServerLoadBalancer.IP != "" { + host = openStackCluster.Status.APIServerLoadBalancer.IP + } else { + host = openStackCluster.Status.APIServerLoadBalancer.InternalIP } - // Set APIEndpoints so the Cluster API Cluster Controller can pull them - openStackCluster.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{ - Host: host, - Port: int32(apiServerPort), + // Control plane endpoint is already set + // Note that checking this here means that we don't re-execute any of + // the branches below if the control plane endpoint is already set. + case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid(): + host = openStackCluster.Spec.ControlPlaneEndpoint.Host + + // API server load balancer is disabled, but floating IP is not. Create + // a floating IP to be attached directly to a control plane host. + case !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false): + fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterResourceName, openStackCluster.Spec.APIServerFloatingIP) + if err != nil { + handleUpdateOSCError(openStackCluster, fmt.Errorf("floating IP cannot be got or created: %w", err)) + return fmt.Errorf("floating IP cannot be got or created: %w", err) } + host = fp.FloatingIP + + // API server load balancer is disabled and we aren't using a control + // plane floating IP. In this case we configure APIServerFixedIP as the + // control plane endpoint and leave it to the user to configure load + // balancing. + case openStackCluster.Spec.APIServerFixedIP != nil: + host = *openStackCluster.Spec.APIServerFixedIP + + // Control plane endpoint is not set, and none can be created + default: + err := fmt.Errorf("unable to determine control plane endpoint") + handleUpdateOSCError(openStackCluster, err) + return err + } + + openStackCluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{ + Host: host, + Port: int32(apiServerPort), } return nil } +// getAPIServerPort returns the port to use for the API server based on the cluster spec. +func getAPIServerPort(openStackCluster *infrav1.OpenStackCluster) int { + switch { + case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid(): + return int(openStackCluster.Spec.ControlPlaneEndpoint.Port) + case openStackCluster.Spec.APIServerPort != nil: + return *openStackCluster.Spec.APIServerPort + } + return 6443 +} + func (r *OpenStackClusterReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { clusterToInfraFn := util.ClusterToInfrastructureMapFunc(ctx, infrav1.GroupVersion.WithKind("OpenStackCluster"), mgr.GetClient(), &infrav1.OpenStackCluster{}) log := ctrl.LoggerFrom(ctx) return ctrl.NewControllerManagedBy(mgr). WithOptions(options). - For(&infrav1.OpenStackCluster{}, - builder.WithPredicates( - predicate.Funcs{ - // Avoid reconciling if the event triggering the reconciliation is related to incremental status updates - UpdateFunc: func(e event.UpdateEvent) bool { - oldCluster := e.ObjectOld.(*infrav1.OpenStackCluster).DeepCopy() - newCluster := e.ObjectNew.(*infrav1.OpenStackCluster).DeepCopy() - oldCluster.Status = infrav1.OpenStackClusterStatus{} - newCluster.Status = infrav1.OpenStackClusterStatus{} - oldCluster.ObjectMeta.ResourceVersion = "" - newCluster.ObjectMeta.ResourceVersion = "" - return !reflect.DeepEqual(oldCluster, newCluster) - }, - }, - ), - ). + For(&infrav1.OpenStackCluster{}). Watches( &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, o client.Object) []reconcile.Request { @@ -625,5 +914,61 @@ func (r *OpenStackClusterReconciler) SetupWithManager(ctx context.Context, mgr c func handleUpdateOSCError(openstackCluster *infrav1.OpenStackCluster, message error) { err := capierrors.UpdateClusterError openstackCluster.Status.FailureReason = &err - openstackCluster.Status.FailureMessage = pointer.String(message.Error()) + openstackCluster.Status.FailureMessage = ptr.To(message.Error()) +} + +// getClusterSubnets retrieves the subnets based on the Subnet filters specified on OpenstackCluster. +func getClusterSubnets(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) ([]subnets.Subnet, error) { + var clusterSubnets []subnets.Subnet + var err error + openStackClusterSubnets := openStackCluster.Spec.Subnets + networkID := "" + if openStackCluster.Status.Network != nil { + networkID = openStackCluster.Status.Network.ID + } + + if len(openStackClusterSubnets) == 0 { + if networkID == "" { + // This should be a validation error + return nil, fmt.Errorf("no network or subnets specified in OpenStackCluster spec") + } + + listOpts := subnets.ListOpts{ + NetworkID: networkID, + } + clusterSubnets, err = networkingService.GetSubnetsByFilter(listOpts) + if err != nil { + err = fmt.Errorf("failed to find subnets: %w", err) + if errors.Is(err, networking.ErrFilterMatch) { + handleUpdateOSCError(openStackCluster, err) + } + return nil, err + } + if len(clusterSubnets) > 2 { + return nil, fmt.Errorf("more than two subnets found in the Network. Specify the subnets in the OpenStackCluster.Spec instead") + } + } else { + for subnet := range openStackClusterSubnets { + filteredSubnet, err := networkingService.GetNetworkSubnetByParam(networkID, &openStackClusterSubnets[subnet]) + if err != nil { + err = fmt.Errorf("failed to find subnet %d in network %s: %w", subnet, networkID, err) + if errors.Is(err, networking.ErrFilterMatch) { + handleUpdateOSCError(openStackCluster, err) + } + return nil, err + } + clusterSubnets = append(clusterSubnets, *filteredSubnet) + + // Constrain the next search to the network of the first subnet + networkID = filteredSubnet.NetworkID + } + } + return clusterSubnets, nil +} + +// setClusterNetwork sets network information in the cluster status from an OpenStack network. +func setClusterNetwork(openStackCluster *infrav1.OpenStackCluster, network *networks.Network) { + openStackCluster.Status.Network.ID = network.ID + openStackCluster.Status.Network.Name = network.Name + openStackCluster.Status.Network.Tags = network.Tags } diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go index a4f0cfb442..21dc0dbe3d 100644 --- a/controllers/openstackcluster_controller_test.go +++ b/controllers/openstackcluster_controller_test.go @@ -19,17 +19,22 @@ package controllers import ( "context" "fmt" + "reflect" + "testing" - "github.com/go-logr/logr" "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" "sigs.k8s.io/cluster-api/util/annotations" @@ -37,7 +42,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients" "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope" ) @@ -56,6 +61,13 @@ var _ = Describe("OpenStackCluster controller", func() { capiClusterName := "capi-cluster" testClusterName := "test-cluster" testNum := 0 + bastionSpec := infrav1.OpenStackMachineSpec{ + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: ptr.To("fake-name"), + }, + }, + } BeforeEach(func() { ctx = context.TODO() @@ -100,7 +112,7 @@ var _ = Describe("OpenStackCluster controller", func() { framework.CreateNamespace(ctx, input) mockCtrl = gomock.NewController(GinkgoT()) - mockScopeFactory = scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()) + mockScopeFactory = scope.NewMockScopeFactory(mockCtrl, "") reconciler = func() *OpenStackClusterReconciler { return &OpenStackClusterReconciler{ Client: k8sClient, @@ -184,31 +196,319 @@ var _ = Describe("OpenStackCluster controller", func() { Expect(err).To(MatchError(clientCreateErr)) Expect(result).To(Equal(reconcile.Result{})) }) - It("should be able to reconcile when bastion is disabled and does not exist", func() { - testCluster.SetName("no-bastion") + It("should be able to reconcile when bastion is explicitly disabled and does not exist", func() { + testCluster.SetName("no-bastion-explicit") + testCluster.Spec = infrav1.OpenStackClusterSpec{ + Bastion: &infrav1.Bastion{Enabled: ptr.To(false)}, + } + err := k8sClient.Create(ctx, testCluster) + Expect(err).To(BeNil()) + err = k8sClient.Create(ctx, capiCluster) + Expect(err).To(BeNil()) + testCluster.Status = infrav1.OpenStackClusterStatus{ + Bastion: &infrav1.BastionStatus{ + ID: "bastion-uuid", + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + }, + }, + } + err = k8sClient.Status().Update(ctx, testCluster) + Expect(err).To(BeNil()) + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) + Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT() + computeClientRecorder.GetServer("bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{}) + + err = deleteBastion(scope, capiCluster, testCluster) + Expect(err).To(BeNil()) + Expect(testCluster.Status.Bastion).To(BeNil()) + }) + It("should adopt an existing bastion even if its uuid is not stored in status", func() { + testCluster.SetName("adopt-existing-bastion") testCluster.Spec = infrav1.OpenStackClusterSpec{ Bastion: &infrav1.Bastion{ - Enabled: false, + Enabled: ptr.To(true), + Spec: &bastionSpec, }, } err := k8sClient.Create(ctx, testCluster) Expect(err).To(BeNil()) err = k8sClient.Create(ctx, capiCluster) Expect(err).To(BeNil()) - scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard()) + testCluster.Status = infrav1.OpenStackClusterStatus{ + Bastion: &infrav1.BastionStatus{ + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + Ports: []infrav1.ResolvedPortSpec{ + { + NetworkID: "network-id", + }, + }, + }, + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "portID1", + }, + }, + }, + }, + Network: &infrav1.NetworkStatusWithSubnets{ + NetworkStatus: infrav1.NetworkStatus{ + Name: "network-name", + ID: "network-id", + }, + }, + } + err = k8sClient.Status().Update(ctx, testCluster) + Expect(err).To(BeNil()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + server := clients.ServerExt{} + server.ID = "adopted-bastion-uuid" + server.Status = "ACTIVE" + + networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT() + networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID1"}}, nil) computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT() computeClientRecorder.ListServers(servers.ListOpts{ Name: "^capi-cluster-bastion$", - }).Return([]clients.ServerExt{}, nil) + }).Return([]clients.ServerExt{server}, nil) + + networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID1"}).Return(make([]floatingips.FloatingIP, 1), nil) + + res, err := reconcileBastion(scope, capiCluster, testCluster) + expectedStatus := &infrav1.BastionStatus{ + ID: "adopted-bastion-uuid", + State: "ACTIVE", + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + Ports: []infrav1.ResolvedPortSpec{ + { + NetworkID: "network-id", + }, + }, + }, + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "portID1", + }, + }, + }, + } + Expect(testCluster.Status.Bastion).To(Equal(expectedStatus), cmp.Diff(testCluster.Status.Bastion, expectedStatus)) + Expect(err).To(BeNil()) + Expect(res).To(BeNil()) + }) + It("should adopt an existing bastion Floating IP if even if its uuid is not stored in status", func() { + testCluster.SetName("requeue-bastion") + testCluster.Spec = infrav1.OpenStackClusterSpec{ + Bastion: &infrav1.Bastion{ + Enabled: ptr.To(true), + Spec: &bastionSpec, + }, + } + err := k8sClient.Create(ctx, testCluster) + Expect(err).To(BeNil()) + err = k8sClient.Create(ctx, capiCluster) + Expect(err).To(BeNil()) + testCluster.Status = infrav1.OpenStackClusterStatus{ + Network: &infrav1.NetworkStatusWithSubnets{ + NetworkStatus: infrav1.NetworkStatus{ + Name: "network-name", + ID: "network-id", + }, + }, + Bastion: &infrav1.BastionStatus{ + ID: "adopted-fip-bastion-uuid", + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + Ports: []infrav1.ResolvedPortSpec{ + { + NetworkID: "network-id", + }, + }, + }, + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "portID1", + }, + }, + }, + }, + } + err = k8sClient.Status().Update(ctx, testCluster) + Expect(err).To(BeNil()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) + Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + server := clients.ServerExt{} + server.ID = "adopted-fip-bastion-uuid" + server.Status = "ACTIVE" networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT() - networkClientRecorder.ListSecGroup(gomock.Any()).Return([]groups.SecGroup{}, nil) + networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID1"}}, nil) + + computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT() + computeClientRecorder.GetServer("adopted-fip-bastion-uuid").Return(&server, nil) + + networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID1"}).Return([]floatingips.FloatingIP{{FloatingIP: "1.2.3.4"}}, nil) + + res, err := reconcileBastion(scope, capiCluster, testCluster) + Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{ + ID: "adopted-fip-bastion-uuid", + FloatingIP: "1.2.3.4", + State: "ACTIVE", + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + Ports: []infrav1.ResolvedPortSpec{ + { + NetworkID: "network-id", + }, + }, + }, + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "portID1", + }, + }, + }, + })) + Expect(err).To(BeNil()) + Expect(res).To(BeNil()) + }) + It("should requeue until bastion becomes active", func() { + testCluster.SetName("requeue-bastion") + testCluster.Spec = infrav1.OpenStackClusterSpec{ + Bastion: &infrav1.Bastion{ + Enabled: ptr.To(true), + Spec: &bastionSpec, + }, + } + err := k8sClient.Create(ctx, testCluster) + Expect(err).To(BeNil()) + err = k8sClient.Create(ctx, capiCluster) + Expect(err).To(BeNil()) + testCluster.Status = infrav1.OpenStackClusterStatus{ + Network: &infrav1.NetworkStatusWithSubnets{ + NetworkStatus: infrav1.NetworkStatus{ + ID: "network-id", + Name: "network-name", + }, + }, + Bastion: &infrav1.BastionStatus{ + ID: "requeue-bastion-uuid", + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + Ports: []infrav1.ResolvedPortSpec{ + { + NetworkID: "network-id", + }, + }, + }, + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "portID1", + }, + }, + }, + }, + } + err = k8sClient.Status().Update(ctx, testCluster) + Expect(err).To(BeNil()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) + Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + server := clients.ServerExt{} + server.ID = "requeue-bastion-uuid" + server.Status = "BUILD" + + computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT() + computeClientRecorder.GetServer("requeue-bastion-uuid").Return(&server, nil) + + res, err := reconcileBastion(scope, capiCluster, testCluster) + Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{ + ID: "requeue-bastion-uuid", + State: "BUILD", + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + Ports: []infrav1.ResolvedPortSpec{ + { + NetworkID: "network-id", + }, + }, + }, + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "portID1", + }, + }, + }, + })) + Expect(err).To(BeNil()) + Expect(res).To(Equal(&reconcile.Result{RequeueAfter: waitForBuildingInstanceToReconcile})) + }) + It("should delete an existing bastion even if its uuid is not stored in status", func() { + testCluster.SetName("delete-existing-bastion") + testCluster.Spec = infrav1.OpenStackClusterSpec{} + err := k8sClient.Create(ctx, testCluster) + Expect(err).To(BeNil()) + err = k8sClient.Create(ctx, capiCluster) + Expect(err).To(BeNil()) + testCluster.Status = infrav1.OpenStackClusterStatus{ + Bastion: &infrav1.BastionStatus{ + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: "imageID", + }, + }, + Network: &infrav1.NetworkStatusWithSubnets{ + NetworkStatus: infrav1.NetworkStatus{ + ID: "network-id", + }, + }, + } + err = k8sClient.Status().Update(ctx, testCluster) + Expect(err).To(BeNil()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) + Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + server := clients.ServerExt{} + server.ID = "delete-bastion-uuid" + + computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT() + computeClientRecorder.ListServers(servers.ListOpts{ + Name: "^capi-cluster-bastion$", + }).Return([]clients.ServerExt{server}, nil) + computeClientRecorder.DeleteServer("delete-bastion-uuid").Return(nil) + computeClientRecorder.GetServer("delete-bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{}) err = deleteBastion(scope, capiCluster, testCluster) Expect(err).To(BeNil()) }) + It("should implicitly filter cluster subnets by cluster network", func() { const externalNetworkID = "a42211a2-4d2c-426f-9413-830e4b4abbbc" const clusterNetworkID = "6c90b532-7ba0-418a-a276-5ae55060b5b0" @@ -216,40 +516,52 @@ var _ = Describe("OpenStackCluster controller", func() { testCluster.SetName("subnet-filtering") testCluster.Spec = infrav1.OpenStackClusterSpec{ - DisableAPIServerFloatingIP: true, - APIServerFixedIP: "10.0.0.1", - ExternalNetworkID: externalNetworkID, - Network: infrav1.NetworkFilter{ - ID: clusterNetworkID, + Bastion: &infrav1.Bastion{ + Enabled: ptr.To(true), + Spec: &bastionSpec, + }, + DisableAPIServerFloatingIP: ptr.To(true), + APIServerFixedIP: ptr.To("10.0.0.1"), + ExternalNetwork: &infrav1.NetworkParam{ + ID: ptr.To(externalNetworkID), + }, + Network: &infrav1.NetworkParam{ + ID: ptr.To(clusterNetworkID), + }, + } + testCluster.Status = infrav1.OpenStackClusterStatus{ + Bastion: &infrav1.BastionStatus{ + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "port-id", + }, + }, + }, }, } err := k8sClient.Create(ctx, testCluster) Expect(err).To(BeNil()) err = k8sClient.Create(ctx, capiCluster) Expect(err).To(BeNil()) - scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT() // Fetch external network - networkClientRecorder.ListNetwork(networks.ListOpts{ - ID: externalNetworkID, - }).Return([]networks.Network{ - { - ID: externalNetworkID, - Name: "external-network", - }, + networkClientRecorder.GetNetwork(externalNetworkID).Return(&networks.Network{ + ID: externalNetworkID, + Name: "external-network", }, nil) // Fetch cluster network - networkClientRecorder.ListNetwork(&networks.ListOpts{ - ID: clusterNetworkID, - }).Return([]networks.Network{ - { - ID: clusterNetworkID, - Name: "cluster-network", - }, + networkClientRecorder.GetNetwork(clusterNetworkID).Return(&networks.Network{ + ID: clusterNetworkID, + Name: "cluster-network", }, nil) // Fetching cluster subnets should be filtered by cluster network id @@ -266,6 +578,126 @@ var _ = Describe("OpenStackCluster controller", func() { err = reconcileNetworkComponents(scope, capiCluster, testCluster) Expect(err).To(BeNil()) }) + + It("should allow two subnets for the cluster network", func() { + const externalNetworkID = "a42211a2-4d2c-426f-9413-830e4b4abbbc" + const clusterNetworkID = "6c90b532-7ba0-418a-a276-5ae55060b5b0" + clusterSubnets := []string{"cad5a91a-36de-4388-823b-b0cc82cadfdc", "e2407c18-c4e7-4d3d-befa-8eec5d8756f2"} + + testCluster.SetName("subnet-filtering") + testCluster.Spec = infrav1.OpenStackClusterSpec{ + Bastion: &infrav1.Bastion{ + Enabled: ptr.To(true), + Spec: &bastionSpec, + }, + DisableAPIServerFloatingIP: ptr.To(true), + APIServerFixedIP: ptr.To("10.0.0.1"), + ExternalNetwork: &infrav1.NetworkParam{ + ID: ptr.To(externalNetworkID), + }, + Network: &infrav1.NetworkParam{ + ID: ptr.To(clusterNetworkID), + }, + Subnets: []infrav1.SubnetParam{ + {ID: &clusterSubnets[0]}, + {ID: &clusterSubnets[1]}, + }, + } + testCluster.Status = infrav1.OpenStackClusterStatus{ + Bastion: &infrav1.BastionStatus{ + Resources: &infrav1.MachineResources{ + Ports: []infrav1.PortStatus{ + { + ID: "port-id", + }, + }, + }, + }, + } + err := k8sClient.Create(ctx, testCluster) + Expect(err).To(BeNil()) + err = k8sClient.Create(ctx, capiCluster) + Expect(err).To(BeNil()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) + Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT() + + // Fetch external network + networkClientRecorder.GetNetwork(externalNetworkID).Return(&networks.Network{ + ID: externalNetworkID, + Name: "external-network", + }, nil) + + // Fetch cluster network + networkClientRecorder.GetNetwork(clusterNetworkID).Return(&networks.Network{ + ID: clusterNetworkID, + Name: "cluster-network", + }, nil) + + networkClientRecorder.GetSubnet(clusterSubnets[0]).Return(&subnets.Subnet{ + ID: clusterSubnets[0], + NetworkID: clusterNetworkID, + Name: "cluster-subnet", + CIDR: "192.168.0.0/24", + }, nil) + + networkClientRecorder.GetSubnet(clusterSubnets[1]).Return(&subnets.Subnet{ + ID: clusterSubnets[1], + NetworkID: clusterNetworkID, + Name: "cluster-subnet-v6", + CIDR: "2001:db8:2222:5555::/64", + }, nil) + + err = reconcileNetworkComponents(scope, capiCluster, testCluster) + Expect(err).To(BeNil()) + Expect(len(testCluster.Status.Network.Subnets)).To(Equal(2)) + }) + + It("should allow fetch network by subnet", func() { + const clusterNetworkID = "6c90b532-7ba0-418a-a276-5ae55060b5b0" + const clusterSubnetID = "cad5a91a-36de-4388-823b-b0cc82cadfdc" + + testCluster.SetName("subnet-filtering") + testCluster.Spec = infrav1.OpenStackClusterSpec{ + DisableAPIServerFloatingIP: ptr.To(true), + APIServerFixedIP: ptr.To("10.0.0.1"), + DisableExternalNetwork: ptr.To(true), + Subnets: []infrav1.SubnetParam{ + {ID: ptr.To(clusterSubnetID)}, + }, + } + err := k8sClient.Create(ctx, testCluster) + Expect(err).To(BeNil()) + err = k8sClient.Create(ctx, capiCluster) + Expect(err).To(BeNil()) + + log := GinkgoLogr + clientScope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, log) + Expect(err).To(BeNil()) + scope := scope.NewWithLogger(clientScope, log) + + networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT() + + // Fetching cluster subnets should be filtered by cluster network id + networkClientRecorder.GetSubnet(clusterSubnetID).Return(&subnets.Subnet{ + ID: clusterSubnetID, + CIDR: "192.168.0.0/24", + NetworkID: clusterNetworkID, + }, nil) + + // Fetch cluster network using the NetworkID from the filtered Subnets + networkClientRecorder.GetNetwork(clusterNetworkID).Return(&networks.Network{ + ID: clusterNetworkID, + }, nil) + + err = reconcileNetworkComponents(scope, capiCluster, testCluster) + Expect(err).To(BeNil()) + Expect(testCluster.Status.Network.ID).To(Equal(clusterNetworkID)) + }) }) func createRequestFromOSCluster(openStackCluster *infrav1.OpenStackCluster) reconcile.Request { @@ -276,3 +708,67 @@ func createRequestFromOSCluster(openStackCluster *infrav1.OpenStackCluster) reco }, } } + +func Test_setClusterNetwork(t *testing.T) { + openStackCluster := &infrav1.OpenStackCluster{} + openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{} + + filterednetwork := &networks.Network{ + ID: "network1", + Name: "network1", + Tags: []string{"tag1", "tag2"}, + } + + setClusterNetwork(openStackCluster, filterednetwork) + expected := infrav1.NetworkStatus{ + ID: "network1", + Name: "network1", + Tags: []string{"tag1", "tag2"}, + } + + if !reflect.DeepEqual(openStackCluster.Status.Network.NetworkStatus, expected) { + t.Errorf("setClusterNetwork() = %v, want %v", openStackCluster.Status.Network.NetworkStatus, expected) + } +} + +func Test_getAPIServerPort(t *testing.T) { + tests := []struct { + name string + openStackCluster *infrav1.OpenStackCluster + want int + }{ + { + name: "default", + openStackCluster: &infrav1.OpenStackCluster{}, + want: 6443, + }, + { + name: "with a control plane endpoint", + openStackCluster: &infrav1.OpenStackCluster{ + Spec: infrav1.OpenStackClusterSpec{ + ControlPlaneEndpoint: &clusterv1.APIEndpoint{ + Host: "192.168.0.1", + Port: 6444, + }, + }, + }, + want: 6444, + }, + { + name: "with API server port", + openStackCluster: &infrav1.OpenStackCluster{ + Spec: infrav1.OpenStackClusterSpec{ + APIServerPort: ptr.To(6445), + }, + }, + want: 6445, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := getAPIServerPort(tt.openStackCluster); got != tt.want { + t.Errorf("getAPIServerPort() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go new file mode 100644 index 0000000000..b739fb25e7 --- /dev/null +++ b/controllers/openstackfloatingippool_controller.go @@ -0,0 +1,493 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + "errors" + "fmt" + "time" + + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/record" + "k8s.io/utils/ptr" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1" + "sigs.k8s.io/cluster-api/util/conditions" + "sigs.k8s.io/cluster-api/util/patch" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + infrav1alpha1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope" +) + +const ( + openStackFloatingIPPool = "OpenStackFloatingIPPool" +) + +var errMaxIPsReached = errors.New("maximum number of IPs reached") + +var backoff = wait.Backoff{ + Steps: 4, + Duration: 10 * time.Millisecond, + Factor: 5.0, + Jitter: 0.1, +} + +// OpenStackFloatingIPPoolReconciler reconciles a OpenStackFloatingIPPool object. +type OpenStackFloatingIPPoolReconciler struct { + Client client.Client + Recorder record.EventRecorder + WatchFilterValue string + ScopeFactory scope.Factory + CaCertificates []byte // PEM encoded ca certificates. + + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=openstackfloatingippools,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=openstackfloatingippools/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddressclaims;ipaddressclaims/status,verbs=get;list;watch;update;create;delete +// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddresses;ipaddresses/status,verbs=get;list;watch;create;update;delete + +func (r *OpenStackFloatingIPPoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { + log := ctrl.LoggerFrom(ctx) + pool := &infrav1alpha1.OpenStackFloatingIPPool{} + if err := r.Client.Get(ctx, req.NamespacedName, pool); err != nil { + return ctrl.Result{}, client.IgnoreNotFound(err) + } + + clientScope, err := r.ScopeFactory.NewClientScopeFromFloatingIPPool(ctx, r.Client, pool, r.CaCertificates, log) + if err != nil { + return reconcile.Result{}, err + } + scope := scope.NewWithLogger(clientScope, log) + + // This is done before deleting the pool, because we want to handle deleted IPs before we delete the pool + if err := r.reconcileIPAddresses(ctx, scope, pool); err != nil { + return ctrl.Result{}, err + } + + if pool.ObjectMeta.DeletionTimestamp.IsZero() { + // Add finalizer if it does not exist + if controllerutil.AddFinalizer(pool, infrav1alpha1.OpenStackFloatingIPPoolFinalizer) { + return ctrl.Result{}, r.Client.Update(ctx, pool) + } + } else { + // Handle deletion + return ctrl.Result{}, r.reconcileDelete(ctx, scope, pool) + } + + patchHelper, err := patch.NewHelper(pool, r.Client) + if err != nil { + return ctrl.Result{}, err + } + + defer func() { + if err := patchHelper.Patch(ctx, pool); err != nil { + if reterr == nil { + reterr = fmt.Errorf("error patching OpenStackFloatingIPPool %s/%s: %w", pool.Namespace, pool.Name, err) + } + } + }() + + if err := r.reconcileFloatingIPNetwork(scope, pool); err != nil { + return ctrl.Result{}, err + } + + claims := &ipamv1.IPAddressClaimList{} + if err := r.Client.List(context.Background(), claims, client.InNamespace(req.Namespace), client.MatchingFields{infrav1alpha1.OpenStackFloatingIPPoolNameIndex: pool.Name}); err != nil { + return ctrl.Result{}, err + } + + for _, claim := range claims.Items { + claim := claim + log := log.WithValues("claim", claim.Name) + if !claim.ObjectMeta.DeletionTimestamp.IsZero() { + continue + } + + if claim.Status.AddressRef.Name == "" { + ipAddress := &ipamv1.IPAddress{} + err := r.Client.Get(ctx, client.ObjectKey{Name: claim.Name, Namespace: claim.Namespace}, ipAddress) + if client.IgnoreNotFound(err) != nil { + return ctrl.Result{}, err + } + if apierrors.IsNotFound(err) { + ip, err := r.getIP(ctx, scope, pool) + if err != nil { + if errors.Is(err, errMaxIPsReached) { + log.Info("Maximum number of IPs reached, will not allocate more IPs.") + return ctrl.Result{}, nil + } + return ctrl.Result{}, err + } + + ipAddress = &ipamv1.IPAddress{ + ObjectMeta: ctrl.ObjectMeta{ + Name: claim.Name, + Namespace: claim.Namespace, + Finalizers: []string{ + infrav1alpha1.DeleteFloatingIPFinalizer, + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: claim.APIVersion, + Kind: claim.Kind, + Name: claim.Name, + UID: claim.UID, + }, + }, + }, + Spec: ipamv1.IPAddressSpec{ + ClaimRef: corev1.LocalObjectReference{ + Name: claim.Name, + }, + PoolRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To(infrav1alpha1.GroupVersion.Group), + Kind: pool.Kind, + Name: pool.Name, + }, + Address: ip, + Prefix: 32, + }, + } + + // Retry creating the IPAddress object + err = wait.ExponentialBackoffWithContext(ctx, backoff, func(ctx context.Context) (bool, error) { + if err := r.Client.Create(ctx, ipAddress); err != nil { + return false, err + } + return true, nil + }) + if err != nil { + // If we failed to create the IPAddress, there might be an IP leak in OpenStack if we also failed to tag the IP after creation + scope.Logger().Error(err, "Failed to create IPAddress", "ip", ip) + return ctrl.Result{}, err + } + } + claim.Status.AddressRef.Name = ipAddress.Name + if err = r.Client.Status().Update(ctx, &claim); err != nil { + log.Error(err, "Failed to update IPAddressClaim status", "claim", claim.Name, "ipaddress", ipAddress.Name) + return ctrl.Result{}, err + } + scope.Logger().Info("Claimed IP", "ip", ipAddress.Spec.Address) + } + } + conditions.MarkTrue(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition) + return ctrl.Result{}, r.Client.Status().Update(ctx, pool) +} + +func (r *OpenStackFloatingIPPoolReconciler) reconcileDelete(ctx context.Context, scope *scope.WithLogger, pool *infrav1alpha1.OpenStackFloatingIPPool) error { + log := ctrl.LoggerFrom(ctx) + ipAddresses := &ipamv1.IPAddressList{} + if err := r.Client.List(ctx, ipAddresses, client.InNamespace(pool.Namespace), client.MatchingFields{infrav1alpha1.OpenStackFloatingIPPoolNameIndex: pool.Name}); err != nil { + return err + } + + // If there are still IPAddress objects that are not deleted, there are still claims on this pool and we should not delete the + // pool because it is needed to clean up the addresses from openstack + if len(ipAddresses.Items) > 0 { + log.Info("Waiting for IPAddress to be deleted before deleting OpenStackFloatingIPPool") + return errors.New("waiting for IPAddress to be deleted, until we can delete the OpenStackFloatingIPPool") + } + + networkingService, err := networking.NewService(scope) + if err != nil { + return err + } + + for _, ip := range diff(pool.Status.AvailableIPs, pool.Spec.PreAllocatedFloatingIPs) { + if err := networkingService.DeleteFloatingIP(pool, ip); err != nil { + return fmt.Errorf("delete floating IP: %w", err) + } + // Remove the IP from the available IPs, so we don't try to delete it again if the reconcile loop runs again + pool.Status.AvailableIPs = diff(pool.Status.AvailableIPs, []string{ip}) + } + + if controllerutil.RemoveFinalizer(pool, infrav1alpha1.OpenStackFloatingIPPoolFinalizer) { + log.Info("Removing finalizer from OpenStackFloatingIPPool") + return r.Client.Update(ctx, pool) + } + return nil +} + +func union(a []string, b []string) []string { + m := make(map[string]struct{}) + for _, item := range a { + m[item] = struct{}{} + } + for _, item := range b { + m[item] = struct{}{} + } + result := make([]string, 0, len(m)) + for item := range m { + result = append(result, item) + } + return result +} + +func diff(a []string, b []string) []string { + m := make(map[string]struct{}) + for _, item := range a { + m[item] = struct{}{} + } + for _, item := range b { + delete(m, item) + } + result := make([]string, 0, len(m)) + for item := range m { + result = append(result, item) + } + return result +} + +func (r *OpenStackFloatingIPPoolReconciler) reconcileIPAddresses(ctx context.Context, scope *scope.WithLogger, pool *infrav1alpha1.OpenStackFloatingIPPool) error { + ipAddresses := &ipamv1.IPAddressList{} + if err := r.Client.List(ctx, ipAddresses, client.InNamespace(pool.Namespace), client.MatchingFields{infrav1alpha1.OpenStackFloatingIPPoolNameIndex: pool.Name}); err != nil { + return err + } + + networkingService, err := networking.NewService(scope) + if err != nil { + return err + } + pool.Status.ClaimedIPs = []string{} + if pool.Status.AvailableIPs == nil { + pool.Status.AvailableIPs = []string{} + } + + for i := 0; i < len(ipAddresses.Items); i++ { + ipAddress := &(ipAddresses.Items[i]) + if ipAddress.ObjectMeta.DeletionTimestamp.IsZero() { + pool.Status.ClaimedIPs = append(pool.Status.ClaimedIPs, ipAddress.Spec.Address) + continue + } + + if controllerutil.ContainsFinalizer(ipAddress, infrav1alpha1.DeleteFloatingIPFinalizer) { + if pool.Spec.ReclaimPolicy == infrav1alpha1.ReclaimDelete && !contains(pool.Spec.PreAllocatedFloatingIPs, ipAddress.Spec.Address) { + if err = networkingService.DeleteFloatingIP(pool, ipAddress.Spec.Address); err != nil { + return fmt.Errorf("delete floating IP %q: %w", ipAddress.Spec.Address, err) + } + } else { + pool.Status.AvailableIPs = append(pool.Status.AvailableIPs, ipAddress.Spec.Address) + } + } + controllerutil.RemoveFinalizer(ipAddress, infrav1alpha1.DeleteFloatingIPFinalizer) + if err := r.Client.Update(ctx, ipAddress); err != nil { + return err + } + } + allIPs := union(pool.Status.AvailableIPs, pool.Spec.PreAllocatedFloatingIPs) + unclaimedIPs := diff(allIPs, pool.Status.ClaimedIPs) + pool.Status.AvailableIPs = diff(unclaimedIPs, pool.Status.FailedIPs) + return nil +} + +func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope *scope.WithLogger, pool *infrav1alpha1.OpenStackFloatingIPPool) (string, error) { + // There's a potential leak of IPs here, if the reconcile loop fails after we claim an IP but before we create the IPAddress object. + var ip string + + networkingService, err := networking.NewService(scope) + if err != nil { + scope.Logger().Error(err, "Failed to create networking service") + return "", err + } + + // Get tagged floating IPs and add them to the available IPs if they are not present in either the available IPs or the claimed IPs + // This is done to prevent leaking floating IPs if the floating IP was created but the IPAddress object was not + if len(pool.Status.AvailableIPs) == 0 { + taggedIPs, err := networkingService.GetFloatingIPsByTag(pool.GetFloatingIPTag()) + if err != nil { + scope.Logger().Error(err, "Failed to get floating IPs by tag", "pool", pool.Name) + return "", err + } + for _, taggedIP := range taggedIPs { + if contains(pool.Status.AvailableIPs, taggedIP.FloatingIP) || contains(pool.Status.ClaimedIPs, taggedIP.FloatingIP) { + continue + } + scope.Logger().Info("Tagged floating IP found that was not known to the pool, adding it to the pool", "ip", taggedIP.FloatingIP) + pool.Status.AvailableIPs = append(pool.Status.AvailableIPs, taggedIP.FloatingIP) + } + } + + if len(pool.Status.AvailableIPs) > 0 { + ip = pool.Status.AvailableIPs[0] + pool.Status.AvailableIPs = pool.Status.AvailableIPs[1:] + pool.Status.ClaimedIPs = append(pool.Status.ClaimedIPs, ip) + } + + if ip != "" { + fp, err := networkingService.GetFloatingIP(ip) + if err != nil { + return "", fmt.Errorf("get floating IP: %w", err) + } + if fp != nil { + pool.Status.ClaimedIPs = append(pool.Status.ClaimedIPs, fp.FloatingIP) + return fp.FloatingIP, nil + } + pool.Status.FailedIPs = append(pool.Status.FailedIPs, ip) + } + maxIPs := ptr.Deref(pool.Spec.MaxIPs, -1) + // If we have reached the maximum number of IPs, we should not create more IPs + if maxIPs != -1 && len(pool.Status.ClaimedIPs) >= maxIPs { + scope.Logger().Info("MaxIPs reached", "pool", pool.Name) + conditions.MarkFalse(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition, infrav1alpha1.MaxIPsReachedReason, clusterv1.ConditionSeverityError, "Maximum number of IPs reached, we will not allocate more IPs for this pool") + return "", errMaxIPsReached + } + + fp, err := networkingService.CreateFloatingIPForPool(pool) + if err != nil { + scope.Logger().Error(err, "Failed to create floating IP", "pool", pool.Name) + conditions.MarkFalse(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition, infrav1.OpenStackErrorReason, clusterv1.ConditionSeverityError, "Failed to create floating IP: %v", err) + return "", err + } + defer func() { + tag := pool.GetFloatingIPTag() + + err := wait.ExponentialBackoffWithContext(ctx, backoff, func(ctx context.Context) (bool, error) { + if err := networkingService.TagFloatingIP(fp.FloatingIP, tag); err != nil { + scope.Logger().Error(err, "Failed to tag floating IP, retrying", "ip", fp.FloatingIP, "tag", tag) + return false, err + } + return true, nil + }) + if err != nil { + scope.Logger().Error(err, "Failed to tag floating IP", "ip", fp.FloatingIP, "tag", tag) + } + }() + + conditions.MarkTrue(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition) + ip = fp.FloatingIP + pool.Status.ClaimedIPs = append(pool.Status.ClaimedIPs, ip) + return ip, nil +} + +func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope *scope.WithLogger, pool *infrav1alpha1.OpenStackFloatingIPPool) error { + // If the pool already has a network, we don't need to do anything + if pool.Status.FloatingIPNetwork != nil { + return nil + } + + networkingService, err := networking.NewService(scope) + if err != nil { + return err + } + + // If the pool does not have a network, we default to a external network if there's only one + var networkParam *infrav1.NetworkParam + if pool.Spec.FloatingIPNetwork == nil { + networkParam = &infrav1.NetworkParam{ + Filter: &infrav1.NetworkFilter{}, + } + } else { + networkParam = pool.Spec.FloatingIPNetwork + } + + network, err := networkingService.GetNetworkByParam(networkParam, networking.ExternalNetworksOnly) + if err != nil { + conditions.MarkFalse(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition, infrav1alpha1.UnableToFindNetwork, clusterv1.ConditionSeverityError, "Failed to find network: %v", err) + return fmt.Errorf("failed to find network: %w", err) + } + + pool.Status.FloatingIPNetwork = &infrav1.NetworkStatus{ + ID: network.ID, + Name: network.Name, + Tags: network.Tags, + } + return nil +} + +func (r *OpenStackFloatingIPPoolReconciler) ipAddressClaimToPoolMapper(_ context.Context, o client.Object) []ctrl.Request { + claim, ok := o.(*ipamv1.IPAddressClaim) + if !ok { + panic(fmt.Sprintf("Expected a IPAddressClaim but got a %T", o)) + } + if claim.Spec.PoolRef.Kind != openStackFloatingIPPool { + return nil + } + return []ctrl.Request{ + { + NamespacedName: client.ObjectKey{ + Name: claim.Spec.PoolRef.Name, + Namespace: claim.Namespace, + }, + }, + } +} + +func (r *OpenStackFloatingIPPoolReconciler) ipAddressToPoolMapper(_ context.Context, o client.Object) []ctrl.Request { + ip, ok := o.(*ipamv1.IPAddress) + if !ok { + panic(fmt.Sprintf("Expected a IPAddress but got a %T", o)) + } + if ip.Spec.PoolRef.Kind != openStackFloatingIPPool { + return nil + } + return []ctrl.Request{ + { + NamespacedName: client.ObjectKey{ + Name: ip.Spec.PoolRef.Name, + Namespace: ip.Namespace, + }, + }, + } +} + +func (r *OpenStackFloatingIPPoolReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &ipamv1.IPAddressClaim{}, infrav1alpha1.OpenStackFloatingIPPoolNameIndex, func(rawObj client.Object) []string { + claim := rawObj.(*ipamv1.IPAddressClaim) + if claim.Spec.PoolRef.Kind != openStackFloatingIPPool { + return nil + } + return []string{claim.Spec.PoolRef.Name} + }); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &ipamv1.IPAddress{}, infrav1alpha1.OpenStackFloatingIPPoolNameIndex, func(rawObj client.Object) []string { + ip := rawObj.(*ipamv1.IPAddress) + if ip.Spec.PoolRef.Kind != openStackFloatingIPPool { + return nil + } + return []string{ip.Spec.PoolRef.Name} + }); err != nil { + return err + } + + return ctrl.NewControllerManagedBy(mgr). + For(&infrav1alpha1.OpenStackFloatingIPPool{}). + Watches( + &ipamv1.IPAddressClaim{}, + handler.EnqueueRequestsFromMapFunc(r.ipAddressClaimToPoolMapper), + ). + Watches( + &ipamv1.IPAddress{}, + handler.EnqueueRequestsFromMapFunc(r.ipAddressToPoolMapper), + ). + Complete(r) +} diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go index 3ec4643456..ee923ec812 100644 --- a/controllers/openstackmachine_controller.go +++ b/controllers/openstackmachine_controller.go @@ -21,18 +21,19 @@ import ( "encoding/base64" "errors" "fmt" - "reflect" "time" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" kerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/tools/record" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" capierrors "sigs.k8s.io/cluster-api/errors" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1" "sigs.k8s.io/cluster-api/util" "sigs.k8s.io/cluster-api/util/annotations" "sigs.k8s.io/cluster-api/util/conditions" @@ -43,16 +44,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/loadbalancer" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking" "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names" ) // OpenStackMachineReconciler reconciles a OpenStackMachine object. @@ -67,15 +67,18 @@ type OpenStackMachineReconciler struct { const ( waitForClusterInfrastructureReadyDuration = 15 * time.Second waitForInstanceBecomeActiveToReconcile = 60 * time.Second + waitForBuildingInstanceToReconcile = 10 * time.Second ) // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines/status,verbs=get;update;patch // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch +// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddressclaims;ipaddressclaims/status,verbs=get;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=ipam.cluster.x-k8s.io,resources=ipaddresses;ipaddresses/status,verbs=get;list;watch // +kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch // +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch -func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { +func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, reterr error) { log := ctrl.LoggerFrom(ctx) // Fetch the OpenStackMachine instance. @@ -89,6 +92,7 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req } log = log.WithValues("openStackMachine", openStackMachine.Name) + log.V(4).Info("Reconciling OpenStackMachine") // Fetch the Machine. machine, err := util.GetOwnerMachine(ctx, r.Client, openStackMachine.ObjectMeta) @@ -136,22 +140,50 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req // Always patch the openStackMachine when exiting this function so we can persist any OpenStackMachine changes. defer func() { if err := patchMachine(ctx, patchHelper, openStackMachine, machine); err != nil { + result = ctrl.Result{} reterr = kerrors.NewAggregate([]error{reterr, err}) } }() - scope, err := r.ScopeFactory.NewClientScopeFromMachine(ctx, r.Client, openStackMachine, r.CaCertificates, log) + clientScope, err := r.ScopeFactory.NewClientScopeFromMachine(ctx, r.Client, openStackMachine, infraCluster, r.CaCertificates, log) if err != nil { return reconcile.Result{}, err } + scope := scope.NewWithLogger(clientScope, log) + + clusterResourceName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name) // Handle deleted machines if !openStackMachine.DeletionTimestamp.IsZero() { - return r.reconcileDelete(scope, cluster, infraCluster, machine, openStackMachine) + return r.reconcileDelete(scope, clusterResourceName, infraCluster, machine, openStackMachine) } // Handle non-deleted clusters - return r.reconcileNormal(ctx, scope, cluster, infraCluster, machine, openStackMachine) + return r.reconcileNormal(ctx, scope, clusterResourceName, infraCluster, machine, openStackMachine) +} + +func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine) (bool, error) { + resolved := openStackMachine.Status.Resolved + if resolved == nil { + resolved = &infrav1.ResolvedMachineSpec{} + openStackMachine.Status.Resolved = resolved + } + // Resolve and store resources + return compute.ResolveMachineSpec(scope, + &openStackMachine.Spec, resolved, + clusterResourceName, openStackMachine.Name, + openStackCluster, getManagedSecurityGroup(openStackCluster, machine)) +} + +func adoptMachineResources(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine) error { + resources := openStackMachine.Status.Resources + if resources == nil { + resources = &infrav1.MachineResources{} + openStackMachine.Status.Resources = resources + } + + // Adopt any existing resources + return compute.AdoptMachineResources(scope, openStackMachine.Status.Resolved, resources) } func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine, options ...patch.Option) error { @@ -184,23 +216,7 @@ func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachi func (r *OpenStackMachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). WithOptions(options). - For( - &infrav1.OpenStackMachine{}, - builder.WithPredicates( - predicate.Funcs{ - // Avoid reconciling if the event triggering the reconciliation is related to incremental status updates - UpdateFunc: func(e event.UpdateEvent) bool { - oldMachine := e.ObjectOld.(*infrav1.OpenStackMachine).DeepCopy() - newMachine := e.ObjectNew.(*infrav1.OpenStackMachine).DeepCopy() - oldMachine.Status = infrav1.OpenStackMachineStatus{} - newMachine.Status = infrav1.OpenStackMachineStatus{} - oldMachine.ObjectMeta.ResourceVersion = "" - newMachine.ObjectMeta.ResourceVersion = "" - return !reflect.DeepEqual(oldMachine, newMachine) - }, - }, - ), - ). + For(&infrav1.OpenStackMachine{}). Watches( &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(util.MachineToInfrastructureMapFunc(infrav1.GroupVersion.WithKind("OpenStackMachine"))), @@ -215,14 +231,16 @@ func (r *OpenStackMachineReconciler) SetupWithManager(ctx context.Context, mgr c handler.EnqueueRequestsFromMapFunc(r.requeueOpenStackMachinesForUnpausedCluster(ctx)), builder.WithPredicates(predicates.ClusterUnpausedAndInfrastructureReady(ctrl.LoggerFrom(ctx))), ). + Watches( + &ipamv1.IPAddressClaim{}, + handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &infrav1.OpenStackMachine{}), + ). Complete(r) } -func (r *OpenStackMachineReconciler) reconcileDelete(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (ctrl.Result, error) { //nolint:unparam +func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (ctrl.Result, error) { //nolint:unparam scope.Logger().Info("Reconciling Machine delete") - clusterName := fmt.Sprintf("%s-%s", cluster.ObjectMeta.Namespace, cluster.Name) - computeService, err := compute.NewService(scope) if err != nil { return ctrl.Result{}, err @@ -233,51 +251,83 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope scope.Scope, cluster return ctrl.Result{}, err } - if openStackCluster.Spec.APIServerLoadBalancer.Enabled { - loadBalancerService, err := loadbalancer.NewService(scope) - if err != nil { + // Nothing to do if the cluster is not ready because no machine resources were created. + if !openStackCluster.Status.Ready || openStackCluster.Status.Network == nil { + // The finalizer should not have been added yet in this case, + // but the following handles the upgrade case. + controllerutil.RemoveFinalizer(openStackMachine, infrav1.MachineFinalizer) + return ctrl.Result{}, nil + } + + // For machines created after v0.10, or any machine which has been + // reconciled at least once by v0.10 or later, status.Resolved always + // exists before any resources are created. We can therefore assume + // that if it does not exist, no resources were created. + // + // There is an upgrade edge case where a machine may have been marked + // deleted before upgrade but we are completing it after upgrade. For + // this use case only we make a best effort to resolve resources before + // continuing, but if we get an error we log it and continue anyway. + // This has the potential to leak resources, but only in this specific + // edge case. The alternative is to continue retrying until it succeeds, + // but that risks never deleting a machine which cannot be resolved due + // to a spec error. + // + // This code can and should be deleted in a future release when we are + // sure that all machines have been reconciled at least by a v0.10 or + // later controller. + if _, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine); err != nil { + // Return the error, but allow the resource to be removed anyway. + controllerutil.RemoveFinalizer(openStackMachine, infrav1.MachineFinalizer) + return ctrl.Result{}, err + } + + // Check for any orphaned resources + // N.B. Unlike resolveMachineResources, we must always look for orphaned resources in the delete path. + if err := adoptMachineResources(scope, openStackMachine); err != nil { + return ctrl.Result{}, fmt.Errorf("adopting machine resources: %w", err) + } + + instanceStatus, err := getInstanceStatus(openStackMachine, computeService) + if err != nil { + return ctrl.Result{}, err + } + + if util.IsControlPlaneMachine(machine) { + if err := removeAPIServerEndpoint(scope, openStackCluster, openStackMachine, instanceStatus, clusterResourceName); err != nil { return ctrl.Result{}, err } + } - err = loadBalancerService.DeleteLoadBalancerMember(openStackCluster, machine, openStackMachine, clusterName) - if err != nil { - conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.LoadBalancerMemberErrorReason, clusterv1.ConditionSeverityWarning, "Machine could not be removed from load balancer: %v", err) - return ctrl.Result{}, err + // If no instance was created we currently need to check for orphaned + // volumes. + if instanceStatus == nil { + if err := computeService.DeleteVolumes(openStackMachine.Name, openStackMachine.Spec.RootVolume, openStackMachine.Spec.AdditionalBlockDevices); err != nil { + return ctrl.Result{}, fmt.Errorf("delete volumes: %w", err) + } + } else { + if err := computeService.DeleteInstance(openStackMachine, instanceStatus); err != nil { + conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceDeleteFailedReason, clusterv1.ConditionSeverityError, "Deleting instance failed: %v", err) + return ctrl.Result{}, fmt.Errorf("delete instance: %w", err) } } - instanceStatus, err := computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name) + trunkSupported, err := networkingService.IsTrunkExtSupported() if err != nil { return ctrl.Result{}, err } - if !openStackCluster.Spec.APIServerLoadBalancer.Enabled && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == "" { - if instanceStatus != nil { - instanceNS, err := instanceStatus.NetworkStatus() - if err != nil { - openStackMachine.SetFailure( - capierrors.UpdateMachineError, - fmt.Errorf("get network status for OpenStack instance %s with ID %s: %v", instanceStatus.Name(), instanceStatus.ID(), err), - ) - return ctrl.Result{}, nil - } - addresses := instanceNS.Addresses() - for _, address := range addresses { - if address.Type == corev1.NodeExternalIP { - if err = networkingService.DeleteFloatingIP(openStackMachine, address.Address); err != nil { - conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.FloatingIPErrorReason, clusterv1.ConditionSeverityError, "Deleting floating IP failed: %v", err) - return ctrl.Result{}, fmt.Errorf("delete floating IP %q: %w", address.Address, err) - } - } + if openStackMachine.Status.Resources != nil { + portsStatus := openStackMachine.Status.Resources.Ports + for _, port := range portsStatus { + if err := networkingService.DeleteInstanceTrunkAndPort(openStackMachine, port, trunkSupported); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete port %q: %w", port.ID, err) } } } - instanceSpec := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "") - - if err := computeService.DeleteInstance(openStackCluster, openStackMachine, instanceStatus, instanceSpec); err != nil { - conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceDeleteFailedReason, clusterv1.ConditionSeverityError, "Deleting instance failed: %v", err) - return ctrl.Result{}, fmt.Errorf("delete instance: %w", err) + if err := r.reconcileDeleteFloatingAddressFromPool(scope, openStackMachine); err != nil { + return ctrl.Result{}, err } controllerutil.RemoveFinalizer(openStackMachine, infrav1.MachineFinalizer) @@ -285,20 +335,211 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope scope.Scope, cluster return ctrl.Result{}, nil } -func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (_ ctrl.Result, reterr error) { +func getInstanceStatus(openStackMachine *infrav1.OpenStackMachine, computeService *compute.Service) (*compute.InstanceStatus, error) { + if openStackMachine.Status.InstanceID != nil { + return computeService.GetInstanceStatus(*openStackMachine.Status.InstanceID) + } + return computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name) +} + +func removeAPIServerEndpoint(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceStatus *compute.InstanceStatus, clusterResourceName string) error { + if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() { + loadBalancerService, err := loadbalancer.NewService(scope) + if err != nil { + return err + } + + err = loadBalancerService.DeleteLoadBalancerMember(openStackCluster, openStackMachine, clusterResourceName) + if err != nil { + conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.LoadBalancerMemberErrorReason, clusterv1.ConditionSeverityWarning, "Machine could not be removed from load balancer: %v", err) + return err + } + return nil + } + + // XXX(mdbooth): This looks wrong to me. Surely we should only ever + // disassociate the floating IP here. I would expect the API server + // floating IP to be created and deleted with the cluster. And if the + // delete behaviour is correct, we leak it if the instance was + // previously deleted. + if openStackCluster.Spec.APIServerFloatingIP == nil && instanceStatus != nil { + instanceNS, err := instanceStatus.NetworkStatus() + if err != nil { + openStackMachine.SetFailure( + capierrors.UpdateMachineError, + fmt.Errorf("get network status for OpenStack instance %s with ID %s: %v", instanceStatus.Name(), instanceStatus.ID(), err), + ) + return nil + } + + networkingService, err := networking.NewService(scope) + if err != nil { + return err + } + + addresses := instanceNS.Addresses() + for _, address := range addresses { + if address.Type == corev1.NodeExternalIP { + if err = networkingService.DeleteFloatingIP(openStackMachine, address.Address); err != nil { + conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.FloatingIPErrorReason, clusterv1.ConditionSeverityError, "Deleting floating IP failed: %v", err) + return fmt.Errorf("delete floating IP %q: %w", address.Address, err) + } + } + } + } + + return nil +} + +// GetPortIDs returns a list of port IDs from a list of PortStatus. +func GetPortIDs(ports []infrav1.PortStatus) []string { + portIDs := make([]string, len(ports)) + for i, port := range ports { + portIDs[i] = port.ID + } + return portIDs +} + +// reconcileFloatingAddressFromPool reconciles the floating IP address from the pool. +// It returns the IPAddressClaim and a boolean indicating if the IPAddressClaim is ready. +func (r *OpenStackMachineReconciler) reconcileFloatingAddressFromPool(ctx context.Context, scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster) (*ipamv1.IPAddressClaim, bool, error) { + if openStackMachine.Spec.FloatingIPPoolRef == nil { + return nil, false, nil + } + var claim *ipamv1.IPAddressClaim + claim, err := r.getOrCreateIPAddressClaimForFloatingAddress(ctx, scope, openStackMachine, openStackCluster) + if err != nil { + conditions.MarkFalse(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition, infrav1.FloatingAddressFromPoolErrorReason, clusterv1.ConditionSeverityInfo, "Failed to reconcile floating IP claims: %v", err) + return nil, true, err + } + if claim.Status.AddressRef.Name == "" { + r.Recorder.Eventf(openStackMachine, corev1.EventTypeNormal, "WaitingForIPAddressClaim", "Waiting for IPAddressClaim %s/%s to be allocated", claim.Namespace, claim.Name) + return claim, true, nil + } + conditions.MarkTrue(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition) + return claim, false, nil +} + +// createIPAddressClaim creates IPAddressClaim for the FloatingAddressFromPool if it does not exist yet. +func (r *OpenStackMachineReconciler) getOrCreateIPAddressClaimForFloatingAddress(ctx context.Context, scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster) (*ipamv1.IPAddressClaim, error) { + var err error + + poolRef := openStackMachine.Spec.FloatingIPPoolRef + claimName := names.GetFloatingAddressClaimName(openStackMachine.Name) + claim := &ipamv1.IPAddressClaim{} + + err = r.Client.Get(ctx, client.ObjectKey{Namespace: openStackMachine.Namespace, Name: claimName}, claim) + if err == nil { + return claim, nil + } else if client.IgnoreNotFound(err) != nil { + return nil, err + } + + claim = &ipamv1.IPAddressClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: claimName, + Namespace: openStackMachine.Namespace, + Labels: map[string]string{ + clusterv1.ClusterNameLabel: openStackCluster.Labels[clusterv1.ClusterNameLabel], + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: openStackMachine.APIVersion, + Kind: openStackMachine.Kind, + Name: openStackMachine.Name, + UID: openStackMachine.UID, + }, + }, + Finalizers: []string{infrav1.IPClaimMachineFinalizer}, + }, + Spec: ipamv1.IPAddressClaimSpec{ + PoolRef: *poolRef, + }, + } + + if err := r.Client.Create(ctx, claim); err != nil { + return nil, err + } + + r.Recorder.Eventf(openStackMachine, corev1.EventTypeNormal, "CreatingIPAddressClaim", "Creating IPAddressClaim %s/%s", claim.Namespace, claim.Name) + scope.Logger().Info("Created IPAddressClaim", "name", claim.Name) + return claim, nil +} + +func (r *OpenStackMachineReconciler) associateIPAddressFromIPAddressClaim(ctx context.Context, scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine, instanceStatus *compute.InstanceStatus, instanceNS *compute.InstanceNetworkStatus, claim *ipamv1.IPAddressClaim) error { + address := &ipamv1.IPAddress{} + addressKey := client.ObjectKey{Namespace: openStackMachine.Namespace, Name: claim.Status.AddressRef.Name} + + if err := r.Client.Get(ctx, addressKey, address); err != nil { + return err + } + + instanceAddresses := instanceNS.Addresses() + for _, instanceAddress := range instanceAddresses { + if instanceAddress.Address == address.Spec.Address { + conditions.MarkTrue(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition) + return nil + } + } + + networkingService, err := networking.NewService(scope) + if err != nil { + return err + } + + fip, err := networkingService.GetFloatingIP(address.Spec.Address) + if err != nil { + return err + } + + if fip == nil { + conditions.MarkFalse(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition, infrav1.FloatingAddressFromPoolErrorReason, clusterv1.ConditionSeverityError, "floating IP does not exist") + return fmt.Errorf("floating IP %q does not exist", address.Spec.Address) + } + + port, err := networkingService.GetPortForExternalNetwork(instanceStatus.ID(), fip.FloatingNetworkID) + if err != nil { + return fmt.Errorf("get port for floating IP %q: %w", fip.FloatingIP, err) + } + + if port == nil { + conditions.MarkFalse(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition, infrav1.FloatingAddressFromPoolErrorReason, clusterv1.ConditionSeverityError, "Can't find port for floating IP %q on external network %s", fip.FloatingIP, fip.FloatingNetworkID) + return fmt.Errorf("port for floating IP %q on network %s does not exist", fip.FloatingIP, fip.FloatingNetworkID) + } + + if err = networkingService.AssociateFloatingIP(openStackMachine, fip, port.ID); err != nil { + return err + } + conditions.MarkTrue(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition) + return nil +} + +func (r *OpenStackMachineReconciler) reconcileDeleteFloatingAddressFromPool(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine) error { + log := scope.Logger().WithValues("openStackMachine", openStackMachine.Name) + log.Info("Reconciling Machine delete floating address from pool") + if openStackMachine.Spec.FloatingIPPoolRef == nil { + return nil + } + claimName := names.GetFloatingAddressClaimName(openStackMachine.Name) + claim := &ipamv1.IPAddressClaim{} + if err := r.Client.Get(context.Background(), client.ObjectKey{Namespace: openStackMachine.Namespace, Name: claimName}, claim); err != nil { + return client.IgnoreNotFound(err) + } + + controllerutil.RemoveFinalizer(claim, infrav1.IPClaimMachineFinalizer) + return r.Client.Update(context.Background(), claim) +} + +func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (_ ctrl.Result, reterr error) { + var err error + // If the OpenStackMachine is in an error state, return early. if openStackMachine.Status.FailureReason != nil || openStackMachine.Status.FailureMessage != nil { scope.Logger().Info("Not reconciling machine in failed state. See openStackMachine.status.failureReason, openStackMachine.status.failureMessage, or previously logged error for details") return ctrl.Result{}, nil } - // If the OpenStackMachine doesn't have our finalizer, add it. - if controllerutil.AddFinalizer(openStackMachine, infrav1.MachineFinalizer) { - // Register the finalizer immediately to avoid orphaning OpenStack resources on delete - return ctrl.Result{}, nil - } - - if !cluster.Status.InfrastructureReady { + if !openStackCluster.Status.Ready { scope.Logger().Info("Cluster infrastructure is not ready yet, re-queuing machine") conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.WaitingForClusterInfrastructureReason, clusterv1.ConditionSeverityInfo, "") return ctrl.Result{RequeueAfter: waitForClusterInfrastructureReadyDuration}, nil @@ -310,36 +551,68 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.WaitingForBootstrapDataReason, clusterv1.ConditionSeverityInfo, "") return ctrl.Result{}, nil } - userData, err := r.getBootstrapData(ctx, machine, openStackMachine) + + changed, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine) if err != nil { return ctrl.Result{}, err } - scope.Logger().Info("Reconciling Machine") - clusterName := fmt.Sprintf("%s-%s", cluster.ObjectMeta.Namespace, cluster.Name) + // Also add the finalizer when writing resolved resources so we can start creating resources on the next reconcile. + if controllerutil.AddFinalizer(openStackMachine, infrav1.MachineFinalizer) { + changed = true + } + + // We requeue if we either added the finalizer or resolved machine + // resources. This means that we never create any resources unless we + // have observed that the finalizer and resolved machine resources were + // successfully written in a previous transaction. This in turn means + // that in the delete path we can be sure that if there are no resolved + // resources then no resources were created. + if changed { + scope.Logger().V(6).Info("Machine resources updated, requeuing") + return ctrl.Result{}, nil + } + + // Check for orphaned resources previously created but not written to the status + if err := adoptMachineResources(scope, openStackMachine); err != nil { + return ctrl.Result{}, fmt.Errorf("adopting machine resources: %w", err) + } + + scope.Logger().Info("Reconciling Machine") + userData, err := r.getBootstrapData(ctx, machine, openStackMachine) + if err != nil { + return ctrl.Result{}, err + } computeService, err := compute.NewService(scope) if err != nil { return ctrl.Result{}, err } + floatingAddressClaim, waitingForFloatingAddress, err := r.reconcileFloatingAddressFromPool(ctx, scope, openStackMachine, openStackCluster) + if err != nil || waitingForFloatingAddress { + return ctrl.Result{}, err + } + networkingService, err := networking.NewService(scope) if err != nil { return ctrl.Result{}, err } - instanceStatus, err := r.getOrCreate(scope.Logger(), cluster, openStackCluster, machine, openStackMachine, computeService, userData) - if err != nil || instanceStatus == nil { - // Conditions set in getOrCreate + err = getOrCreateMachinePorts(openStackMachine, networkingService) + if err != nil { return ctrl.Result{}, err } + portIDs := GetPortIDs(openStackMachine.Status.Resources.Ports) - // TODO(sbueringer) From CAPA: TODO(ncdc): move this validation logic into a validating webhook (for us: create validation logic in webhook) - - openStackMachine.Spec.ProviderID = pointer.String(fmt.Sprintf("openstack:///%s", instanceStatus.ID())) - openStackMachine.Spec.InstanceID = pointer.String(instanceStatus.ID()) + instanceStatus, err := r.getOrCreateInstance(scope.Logger(), openStackCluster, machine, openStackMachine, computeService, userData, portIDs) + if err != nil || instanceStatus == nil { + // Conditions set in getOrCreateInstance + return ctrl.Result{}, err + } state := instanceStatus.State() + openStackMachine.Status.InstanceID = ptr.To(instanceStatus.ID()) openStackMachine.Status.InstanceState = &state instanceNS, err := instanceStatus.NetworkStatus() @@ -358,10 +631,21 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope }) openStackMachine.Status.Addresses = addresses + if floatingAddressClaim != nil { + if err := r.associateIPAddressFromIPAddressClaim(ctx, scope, openStackMachine, instanceStatus, instanceNS, floatingAddressClaim); err != nil { + conditions.MarkFalse(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition, infrav1.FloatingAddressFromPoolErrorReason, clusterv1.ConditionSeverityError, "Failed while associating ip from pool: %v", err) + return ctrl.Result{}, err + } + conditions.MarkTrue(openStackMachine, infrav1.FloatingAddressFromPoolReadyCondition) + } + switch instanceStatus.State() { case infrav1.InstanceStateActive: scope.Logger().Info("Machine instance state is ACTIVE", "id", instanceStatus.ID()) conditions.MarkTrue(openStackMachine, infrav1.InstanceReadyCondition) + + // Set properties required by CAPI machine controller + openStackMachine.Spec.ProviderID = ptr.To(fmt.Sprintf("openstack:///%s", instanceStatus.ID())) openStackMachine.Status.Ready = true case infrav1.InstanceStateError: // If the machine has a NodeRef then it must have been working at some point, @@ -379,11 +663,15 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope scope.Logger().Info("Machine instance state is DELETED, no actions") conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceDeletedReason, clusterv1.ConditionSeverityError, "") return ctrl.Result{}, nil + case infrav1.InstanceStateBuild, infrav1.InstanceStateUndefined: + scope.Logger().Info("Waiting for instance to become ACTIVE", "id", instanceStatus.ID(), "status", instanceStatus.State()) + return ctrl.Result{RequeueAfter: waitForBuildingInstanceToReconcile}, nil default: // The other state is normal (for example, migrating, shutoff) but we don't want to proceed until it's ACTIVE // due to potential conflict or unexpected actions scope.Logger().Info("Waiting for instance to become ACTIVE", "id", instanceStatus.ID(), "status", instanceStatus.State()) conditions.MarkUnknown(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceNotReadyReason, "Instance state is not handled: %s", instanceStatus.State()) + return ctrl.Result{RequeueAfter: waitForInstanceBecomeActiveToReconcile}, nil } @@ -392,26 +680,51 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope return ctrl.Result{}, nil } - if openStackCluster.Spec.APIServerLoadBalancer.Enabled { - err = r.reconcileLoadBalancerMember(scope, openStackCluster, openStackMachine, instanceNS, clusterName) + err = r.reconcileAPIServerLoadBalancer(scope, openStackCluster, openStackMachine, instanceStatus, instanceNS, clusterResourceName) + if err != nil { + return ctrl.Result{}, err + } + + conditions.MarkTrue(openStackMachine, infrav1.APIServerIngressReadyCondition) + scope.Logger().Info("Reconciled Machine create successfully") + return ctrl.Result{}, nil +} + +func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceStatus *compute.InstanceStatus, instanceNS *compute.InstanceNetworkStatus, clusterResourceName string) error { + scope.Logger().Info("Reconciling APIServerLoadBalancer") + computeService, err := compute.NewService(scope) + if err != nil { + return err + } + + networkingService, err := networking.NewService(scope) + if err != nil { + return err + } + + if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() { + err = r.reconcileLoadBalancerMember(scope, openStackCluster, openStackMachine, instanceNS, clusterResourceName) if err != nil { conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.LoadBalancerMemberErrorReason, clusterv1.ConditionSeverityError, "Reconciling load balancer member failed: %v", err) - return ctrl.Result{}, fmt.Errorf("reconcile load balancer member: %w", err) + return fmt.Errorf("reconcile load balancer member: %w", err) } - } else if !openStackCluster.Spec.DisableAPIServerFloatingIP { - floatingIPAddress := openStackCluster.Spec.ControlPlaneEndpoint.Host - if openStackCluster.Spec.APIServerFloatingIP != "" { + } else if !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) { + var floatingIPAddress *string + switch { + case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid(): + floatingIPAddress = &openStackCluster.Spec.ControlPlaneEndpoint.Host + case openStackCluster.Spec.APIServerFloatingIP != nil: floatingIPAddress = openStackCluster.Spec.APIServerFloatingIP } - fp, err := networkingService.GetOrCreateFloatingIP(openStackMachine, openStackCluster, clusterName, floatingIPAddress) + fp, err := networkingService.GetOrCreateFloatingIP(openStackMachine, openStackCluster, clusterResourceName, floatingIPAddress) if err != nil { conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.FloatingIPErrorReason, clusterv1.ConditionSeverityError, "Floating IP cannot be obtained or created: %v", err) - return ctrl.Result{}, fmt.Errorf("get or create floating IP %q: %w", floatingIPAddress, err) + return fmt.Errorf("get or create floating IP %v: %w", floatingIPAddress, err) } port, err := computeService.GetManagementPort(openStackCluster, instanceStatus) if err != nil { conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.FloatingIPErrorReason, clusterv1.ConditionSeverityError, "Obtaining management port for control plane machine failed: %v", err) - return ctrl.Result{}, fmt.Errorf("get management port for control plane machine: %w", err) + return fmt.Errorf("get management port for control plane machine: %w", err) } if fp.PortID != "" { @@ -420,56 +733,99 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope err = networkingService.AssociateFloatingIP(openStackMachine, fp, port.ID) if err != nil { conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.FloatingIPErrorReason, clusterv1.ConditionSeverityError, "Associating floating IP failed: %v", err) - return ctrl.Result{}, fmt.Errorf("associate floating IP %q with port %q: %w", fp.FloatingIP, port.ID, err) + return fmt.Errorf("associate floating IP %q with port %q: %w", fp.FloatingIP, port.ID, err) } } } conditions.MarkTrue(openStackMachine, infrav1.APIServerIngressReadyCondition) - - scope.Logger().Info("Reconciled Machine create successfully") - return ctrl.Result{}, nil + return nil } -func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, computeService *compute.Service, userData string) (*compute.InstanceStatus, error) { - instanceStatus, err := computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name) - if err != nil { - logger.Info("Unable to get OpenStack instance", "name", openStackMachine.Name) - conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.OpenStackErrorReason, clusterv1.ConditionSeverityError, err.Error()) - return nil, err +func getOrCreateMachinePorts(openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service) error { + resolved := openStackMachine.Status.Resolved + if resolved == nil { + return errors.New("machine resolved is nil") + } + resources := openStackMachine.Status.Resources + if resources == nil { + return errors.New("machine resources is nil") + } + desiredPorts := resolved.Ports + + if len(desiredPorts) == len(resources.Ports) { + return nil } + if err := networkingService.CreatePorts(openStackMachine, desiredPorts, resources); err != nil { + return fmt.Errorf("creating ports: %w", err) + } + + return nil +} + +func (r *OpenStackMachineReconciler) getOrCreateInstance(logger logr.Logger, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, computeService *compute.Service, userData string, portIDs []string) (*compute.InstanceStatus, error) { + var instanceStatus *compute.InstanceStatus + var err error + if openStackMachine.Status.InstanceID != nil { + instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Status.InstanceID) + if err != nil { + logger.Info("Unable to get OpenStack instance", "name", openStackMachine.Name) + conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.OpenStackErrorReason, clusterv1.ConditionSeverityError, err.Error()) + return nil, err + } + } if instanceStatus == nil { - if openStackMachine.Spec.InstanceID != nil { - logger.Info("Not reconciling machine in failed state. The previously existing OpenStack instance is no longer available") - conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceNotFoundReason, clusterv1.ConditionSeverityError, "virtual machine no longer exists") - openStackMachine.SetFailure(capierrors.UpdateMachineError, errors.New("virtual machine no longer exists")) - return nil, nil + // Check if there is an existing instance with machine name, in case where instance ID would not have been stored in machine status + if instanceStatus, err = computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name); err == nil { + if instanceStatus != nil { + return instanceStatus, nil + } + if openStackMachine.Status.InstanceID != nil { + logger.Info("Not reconciling machine in failed state. The previously existing OpenStack instance is no longer available") + conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceNotFoundReason, clusterv1.ConditionSeverityError, "virtual machine no longer exists") + openStackMachine.SetFailure(capierrors.UpdateMachineError, errors.New("virtual machine no longer exists")) + return nil, nil + } + } + instanceSpec, err := machineToInstanceSpec(openStackCluster, machine, openStackMachine, userData) + if err != nil { + return nil, err } - instanceSpec := machineToInstanceSpec(openStackCluster, machine, openStackMachine, userData) + logger.Info("Machine does not exist, creating Machine", "name", openStackMachine.Name) - instanceStatus, err = computeService.CreateInstance(openStackMachine, openStackCluster, instanceSpec, cluster.Name) + instanceStatus, err = computeService.CreateInstance(openStackMachine, instanceSpec, portIDs) if err != nil { conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceCreateFailedReason, clusterv1.ConditionSeverityError, err.Error()) return nil, fmt.Errorf("create OpenStack instance: %w", err) } } - return instanceStatus, nil } -func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, userData string) *compute.InstanceSpec { +func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, userData string) (*compute.InstanceSpec, error) { + resolved := openStackMachine.Status.Resolved + if resolved == nil { + return nil, errors.New("machine resolved is nil") + } + + serverMetadata := make(map[string]string, len(openStackMachine.Spec.ServerMetadata)) + for i := range openStackMachine.Spec.ServerMetadata { + key := openStackMachine.Spec.ServerMetadata[i].Key + value := openStackMachine.Spec.ServerMetadata[i].Value + serverMetadata[key] = value + } + instanceSpec := compute.InstanceSpec{ Name: openStackMachine.Name, - Image: openStackMachine.Spec.Image, - ImageUUID: openStackMachine.Spec.ImageUUID, + ImageID: resolved.ImageID, Flavor: openStackMachine.Spec.Flavor, SSHKeyName: openStackMachine.Spec.SSHKeyName, UserData: userData, - Metadata: openStackMachine.Spec.ServerMetadata, + Metadata: serverMetadata, ConfigDrive: openStackMachine.Spec.ConfigDrive != nil && *openStackMachine.Spec.ConfigDrive, RootVolume: openStackMachine.Spec.RootVolume, AdditionalBlockDevices: openStackMachine.Spec.AdditionalBlockDevices, - ServerGroupID: openStackMachine.Spec.ServerGroupID, + ServerGroupID: resolved.ServerGroupID, Trunk: openStackMachine.Spec.Trunk, } @@ -478,57 +834,39 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine * instanceSpec.FailureDomain = *machine.Spec.FailureDomain } - machineTags := []string{} - - // Append machine specific tags - machineTags = append(machineTags, openStackMachine.Spec.Tags...) + instanceSpec.Tags = compute.InstanceTags(&openStackMachine.Spec, openStackCluster) - // Append cluster scope tags - machineTags = append(machineTags, openStackCluster.Spec.Tags...) + return &instanceSpec, nil +} - // tags need to be unique or the "apply tags" call will fail. - deduplicate := func(tags []string) []string { - seen := make(map[string]struct{}, len(machineTags)) - unique := make([]string, 0, len(machineTags)) - for _, tag := range tags { - if _, ok := seen[tag]; !ok { - seen[tag] = struct{}{} - unique = append(unique, tag) - } - } - return unique +// getManagedSecurityGroup returns the ID of the security group managed by the +// OpenStackCluster whether it's a control plane or a worker machine. +func getManagedSecurityGroup(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine) *string { + if openStackCluster.Spec.ManagedSecurityGroups == nil { + return nil } - machineTags = deduplicate(machineTags) - - instanceSpec.Tags = machineTags - instanceSpec.SecurityGroups = openStackMachine.Spec.SecurityGroups - if openStackCluster.Spec.ManagedSecurityGroups { - var managedSecurityGroup string - if util.IsControlPlaneMachine(machine) && openStackCluster.Status.ControlPlaneSecurityGroup != nil { - managedSecurityGroup = openStackCluster.Status.ControlPlaneSecurityGroup.ID - } else if openStackCluster.Status.WorkerSecurityGroup != nil { - managedSecurityGroup = openStackCluster.Status.WorkerSecurityGroup.ID + if util.IsControlPlaneMachine(machine) { + if openStackCluster.Status.ControlPlaneSecurityGroup != nil { + return &openStackCluster.Status.ControlPlaneSecurityGroup.ID + } + } else { + if openStackCluster.Status.WorkerSecurityGroup != nil { + return &openStackCluster.Status.WorkerSecurityGroup.ID } - - instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{ - ID: managedSecurityGroup, - }) } - instanceSpec.Ports = openStackMachine.Spec.Ports - - return &instanceSpec + return nil } -func (r *OpenStackMachineReconciler) reconcileLoadBalancerMember(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceNS *compute.InstanceNetworkStatus, clusterName string) error { +func (r *OpenStackMachineReconciler) reconcileLoadBalancerMember(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceNS *compute.InstanceNetworkStatus, clusterResourceName string) error { ip := instanceNS.IP(openStackCluster.Status.Network.Name) loadbalancerService, err := loadbalancer.NewService(scope) if err != nil { return err } - return loadbalancerService.ReconcileLoadBalancerMember(openStackCluster, openStackMachine, clusterName, ip) + return loadbalancerService.ReconcileLoadBalancerMember(openStackCluster, openStackMachine, clusterResourceName, ip) } // OpenStackClusterToOpenStackMachines is a handler.ToRequestsFunc to be used to enqeue requests for reconciliation diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go index 84151e5dfa..4a82b3d850 100644 --- a/controllers/openstackmachine_controller_test.go +++ b/controllers/openstackmachine_controller_test.go @@ -17,15 +17,30 @@ limitations under the License. package controllers import ( + "fmt" + "reflect" "testing" + "github.com/go-logr/logr/testr" + "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" + "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks" + "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope" ) const ( @@ -35,10 +50,10 @@ const ( controlPlaneSecurityGroupUUID = "c9817a91-4821-42db-8367-2301002ab659" workerSecurityGroupUUID = "9c6c0d28-03c9-436c-815d-58440ac2c1c8" serverGroupUUID = "7b940d62-68ef-4e42-a76a-1a62e290509c" + imageUUID = "ce96e584-7ebc-46d6-9e55-987d72e3806c" openStackMachineName = "test-openstack-machine" namespace = "test-namespace" - imageName = "test-image" flavorName = "test-flavor" sshKeyName = "test-ssh-key" failureDomain = "test-failure-domain" @@ -56,8 +71,8 @@ func getDefaultOpenStackCluster() *infrav1.OpenStackCluster { {ID: subnetUUID}, }, }, - ControlPlaneSecurityGroup: &infrav1.SecurityGroup{ID: controlPlaneSecurityGroupUUID}, - WorkerSecurityGroup: &infrav1.SecurityGroup{ID: workerSecurityGroupUUID}, + ControlPlaneSecurityGroup: &infrav1.SecurityGroupStatus{ID: controlPlaneSecurityGroupUUID}, + WorkerSecurityGroup: &infrav1.SecurityGroupStatus{ID: workerSecurityGroupUUID}, }, } } @@ -65,7 +80,7 @@ func getDefaultOpenStackCluster() *infrav1.OpenStackCluster { func getDefaultMachine() *clusterv1.Machine { return &clusterv1.Machine{ Spec: clusterv1.MachineSpec{ - FailureDomain: pointer.String(failureDomain), + FailureDomain: ptr.To(failureDomain), }, } } @@ -81,16 +96,22 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine { // InstanceID is set by the controller // FloatingIP is only used by the cluster controller for the Bastion // TODO: Test Networks, Ports, Subnet, and Trunk separately - CloudName: "test-cloud", Flavor: flavorName, - Image: imageName, + Image: infrav1.ImageParam{ID: ptr.To(imageUUID)}, SSHKeyName: sshKeyName, Tags: []string{"test-tag"}, - ServerMetadata: map[string]string{ - "test-metadata": "test-value", + ServerMetadata: []infrav1.ServerMetadata{ + {Key: "test-metadata", Value: "test-value"}, + }, + ConfigDrive: ptr.To(true), + SecurityGroups: []infrav1.SecurityGroupParam{}, + ServerGroup: &infrav1.ServerGroupParam{ID: ptr.To(serverGroupUUID)}, + }, + Status: infrav1.OpenStackMachineStatus{ + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: imageUUID, + ServerGroupID: serverGroupUUID, }, - ConfigDrive: pointer.Bool(true), - ServerGroupID: serverGroupUUID, }, } } @@ -98,15 +119,15 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine { func getDefaultInstanceSpec() *compute.InstanceSpec { return &compute.InstanceSpec{ Name: openStackMachineName, - Image: imageName, + ImageID: imageUUID, Flavor: flavorName, SSHKeyName: sshKeyName, UserData: "user-data", Metadata: map[string]string{ "test-metadata": "test-value", }, - ConfigDrive: *pointer.Bool(true), - FailureDomain: *pointer.String(failureDomain), + ConfigDrive: *ptr.To(true), + FailureDomain: *ptr.To(failureDomain), ServerGroupID: serverGroupUUID, Tags: []string{"test-tag"}, } @@ -130,87 +151,423 @@ func Test_machineToInstanceSpec(t *testing.T) { wantInstanceSpec: getDefaultInstanceSpec, }, { - name: "Control plane security group", + name: "Tags", openStackCluster: func() *infrav1.OpenStackCluster { c := getDefaultOpenStackCluster() - c.Spec.ManagedSecurityGroups = true + c.Spec.Tags = []string{"cluster-tag", "duplicate-tag"} return c }, - machine: func() *clusterv1.Machine { - m := getDefaultMachine() - m.Labels = map[string]string{ - clusterv1.MachineControlPlaneLabel: "true", - } + machine: getDefaultMachine, + openStackMachine: func() *infrav1.OpenStackMachine { + m := getDefaultOpenStackMachine() + m.Spec.Tags = []string{"machine-tag", "duplicate-tag"} return m }, - openStackMachine: getDefaultOpenStackMachine, wantInstanceSpec: func() *compute.InstanceSpec { i := getDefaultInstanceSpec() - i.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: controlPlaneSecurityGroupUUID}} + i.Tags = []string{"machine-tag", "duplicate-tag", "cluster-tag"} return i }, }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + got, _ := machineToInstanceSpec(tt.openStackCluster(), tt.machine(), tt.openStackMachine(), "user-data") + wanted := tt.wantInstanceSpec() + + g.Expect(got).To(Equal(wanted), cmp.Diff(got, wanted)) + }) + } +} + +func TestGetPortIDs(t *testing.T) { + tests := []struct { + name string + ports []infrav1.PortStatus + want []string + }{ { - name: "Worker security group", - openStackCluster: func() *infrav1.OpenStackCluster { - c := getDefaultOpenStackCluster() - c.Spec.ManagedSecurityGroups = true - return c + name: "Empty ports", + ports: []infrav1.PortStatus{}, + want: []string{}, + }, + { + name: "Single port", + ports: []infrav1.PortStatus{ + {ID: "port1"}, }, - machine: getDefaultMachine, - openStackMachine: getDefaultOpenStackMachine, - wantInstanceSpec: func() *compute.InstanceSpec { - i := getDefaultInstanceSpec() - i.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: workerSecurityGroupUUID}} - return i + want: []string{"port1"}, + }, + { + name: "Multiple ports", + ports: []infrav1.PortStatus{ + {ID: "port1"}, + {ID: "port2"}, + {ID: "port3"}, }, + want: []string{"port1", "port2", "port3"}, }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := GetPortIDs(tt.ports) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetPortIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_reconcileDelete(t *testing.T) { + const ( + instanceUUID = "8308882f-5e46-47e6-8e12-1fe869c43d1d" + portUUID = "55eac199-4836-4a98-b31c-9f65f382ad46" + rootVolumeUUID = "4724a66d-bd5e-47f3-bb57-a67fcb4168e0" + trunkUUID = "9d348baa-93b1-4e63-932f-dd0527fbd789" + + imageName = "my-image" + ) + + // ******************* + // START OF TEST CASES + // ******************* + + type recorders struct { + compute *mock.MockComputeClientMockRecorder + image *mock.MockImageClientMockRecorder + network *mock.MockNetworkClientMockRecorder + volume *mock.MockVolumeClientMockRecorder + } + + defaultImage := infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: ptr.To(imageName), + }, + } + + defaultResolvedPorts := []infrav1.ResolvedPortSpec{ { - name: "Extra security group", - openStackCluster: func() *infrav1.OpenStackCluster { - c := getDefaultOpenStackCluster() - c.Spec.ManagedSecurityGroups = true - return c + Name: openStackMachineName + "-0", + Description: "my test port", + NetworkID: networkUUID, + }, + } + defaultPortsStatus := []infrav1.PortStatus{ + { + ID: portUUID, + }, + } + + deleteDefaultPorts := func(r *recorders) { + trunkExtension := extensions.Extension{} + trunkExtension.Alias = "trunk" + r.network.ListExtensions().Return([]extensions.Extension{trunkExtension}, nil) + r.network.ListTrunk(trunks.ListOpts{PortID: portUUID}).Return([]trunks.Trunk{{ID: trunkUUID}}, nil) + r.network.DeleteTrunk(trunkUUID).Return(nil) + r.network.DeletePort(portUUID).Return(nil) + } + + deleteServerByID := func(r *recorders) { + r.compute.GetServer(instanceUUID).Return(&clients.ServerExt{ + Server: servers.Server{ + ID: instanceUUID, + Name: openStackMachineName, }, - machine: getDefaultMachine, - openStackMachine: func() *infrav1.OpenStackMachine { - m := getDefaultOpenStackMachine() - m.Spec.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: extraSecurityGroupUUID}} - return m + }, nil) + r.compute.DeleteServer(instanceUUID).Return(nil) + r.compute.GetServer(instanceUUID).Return(nil, gophercloud.ErrDefault404{}) + } + deleteServerByName := func(r *recorders) { + r.compute.ListServers(servers.ListOpts{ + Name: "^" + openStackMachineName + "$", + }).Return([]clients.ServerExt{ + {Server: servers.Server{ + ID: instanceUUID, + Name: openStackMachineName, + }}, + }, nil) + r.compute.DeleteServer(instanceUUID).Return(nil) + r.compute.GetServer(instanceUUID).Return(nil, gophercloud.ErrDefault404{}) + } + + deleteMissingServerByName := func(r *recorders) { + // Lookup server by name because it is not in status. + // Don't find it. + r.compute.ListServers(servers.ListOpts{ + Name: "^" + openStackMachineName + "$", + }).Return([]clients.ServerExt{}, nil) + } + + deleteRootVolume := func(r *recorders) { + // Fetch volume by name + volumeName := fmt.Sprintf("%s-root", openStackMachineName) + r.volume.ListVolumes(volumes.ListOpts{ + AllTenants: false, + Name: volumeName, + TenantID: "", + }).Return([]volumes.Volume{{ + ID: rootVolumeUUID, + Name: volumeName, + }}, nil) + + // Delete volume + r.volume.DeleteVolume(rootVolumeUUID, volumes.DeleteOpts{}).Return(nil) + } + + adoptExistingPorts := func(r *recorders) { + r.network.ListPort(ports.ListOpts{ + NetworkID: networkUUID, + Name: openStackMachineName + "-0", + }).Return([]ports.Port{{ID: portUUID}}, nil) + } + + resolveImage := func(r *recorders) { + r.image.ListImages(images.ListOpts{ + Name: imageName, + }).Return([]images.Image{{ID: imageUUID}}, nil) + } + + tests := []struct { + name string + osMachine infrav1.OpenStackMachine + expect func(r *recorders) + wantErr bool + wantRemoveFinalizer bool + clusterNotReady bool + }{ + { + name: "No volumes, resolved and resources populated", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + }, + Status: infrav1.OpenStackMachineStatus{ + InstanceID: ptr.To(instanceUUID), + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: imageUUID, + Ports: defaultResolvedPorts, + }, + Resources: &infrav1.MachineResources{ + Ports: defaultPortsStatus, + }, + }, }, - wantInstanceSpec: func() *compute.InstanceSpec { - i := getDefaultInstanceSpec() - i.SecurityGroups = []infrav1.SecurityGroupFilter{ - {ID: extraSecurityGroupUUID}, - {ID: workerSecurityGroupUUID}, - } - return i + expect: func(r *recorders) { + deleteServerByID(r) + deleteDefaultPorts(r) }, + wantRemoveFinalizer: true, }, { - name: "Tags", - openStackCluster: func() *infrav1.OpenStackCluster { - c := getDefaultOpenStackCluster() - c.Spec.Tags = []string{"cluster-tag", "duplicate-tag"} - return c + name: "Root volume, resolved and resources populated", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + RootVolume: &infrav1.RootVolume{ + SizeGiB: 50, + }, + }, + Status: infrav1.OpenStackMachineStatus{ + InstanceID: ptr.To(instanceUUID), + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: imageUUID, + Ports: defaultResolvedPorts, + }, + Resources: &infrav1.MachineResources{ + Ports: defaultPortsStatus, + }, + }, }, - machine: getDefaultMachine, - openStackMachine: func() *infrav1.OpenStackMachine { - m := getDefaultOpenStackMachine() - m.Spec.Tags = []string{"machine-tag", "duplicate-tag"} - return m + expect: func(r *recorders) { + // Server exists, so we don't delete root volume explicitly + deleteServerByID(r) + deleteDefaultPorts(r) }, - wantInstanceSpec: func() *compute.InstanceSpec { - i := getDefaultInstanceSpec() - i.Tags = []string{"machine-tag", "duplicate-tag", "cluster-tag"} - return i + wantRemoveFinalizer: true, + }, + { + name: "Root volume, machine not created, resolved and resources populated", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + RootVolume: &infrav1.RootVolume{ + SizeGiB: 50, + }, + }, + Status: infrav1.OpenStackMachineStatus{ + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: imageUUID, + Ports: defaultResolvedPorts, + }, + Resources: &infrav1.MachineResources{ + Ports: defaultPortsStatus, + }, + }, + }, + expect: func(r *recorders) { + deleteMissingServerByName(r) + deleteRootVolume(r) + deleteDefaultPorts(r) + }, + wantRemoveFinalizer: true, + }, + { + // N.B. The 'no resolved but resource exist' case can + // only happen across an upgrade. At some point in the + // future we should stop handling it. + name: "No volumes, no resolved or resources, instance exists", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + }, + Status: infrav1.OpenStackMachineStatus{ + // Unlike resolved and resources, + // instanceID will have been converted + // from the previous API version. + InstanceID: ptr.To(instanceUUID), + }, + }, + expect: func(r *recorders) { + resolveImage(r) + adoptExistingPorts(r) + deleteServerByID(r) + deleteDefaultPorts(r) }, + wantRemoveFinalizer: true, + }, + { + // This is an upgrade case because from v0.10 onwards + // we don't add the finalizer until we add resolved, so + // this can no longer occur. This will stop working when + // we remove handling for empty resolved on delete. + name: "Invalid image, no resolved or resources", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + }, + }, + expect: func(r *recorders) { + r.image.ListImages(images.ListOpts{Name: imageName}).Return([]images.Image{}, nil) + }, + wantErr: true, + wantRemoveFinalizer: true, + }, + { + name: "No instance id, server and ports exist", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + }, + Status: infrav1.OpenStackMachineStatus{ + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: imageUUID, + Ports: defaultResolvedPorts, + }, + Resources: &infrav1.MachineResources{ + Ports: defaultPortsStatus, + }, + }, + }, + expect: func(r *recorders) { + deleteServerByName(r) + deleteDefaultPorts(r) + }, + wantRemoveFinalizer: true, + }, + { + name: "Adopt ports error should fail deletion and retry", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + }, + Status: infrav1.OpenStackMachineStatus{ + Resolved: &infrav1.ResolvedMachineSpec{ + ImageID: imageUUID, + Ports: defaultResolvedPorts, + }, + }, + }, + expect: func(r *recorders) { + r.network.ListPort(ports.ListOpts{ + NetworkID: networkUUID, + Name: openStackMachineName + "-0", + }).Return(nil, fmt.Errorf("error adopting ports")) + }, + wantErr: true, + wantRemoveFinalizer: false, + }, + { + // This is an upgrade case because from v0.10 onwards we + // should not have added the finalizer until the cluster + // is ready. + name: "Cluster not ready should remove finalizer", + osMachine: infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: defaultImage, + }, + }, + clusterNotReady: true, + wantRemoveFinalizer: true, }, } - for _, tt := range tests { + for i := range tests { + tt := &tests[i] t.Run(tt.name, func(t *testing.T) { - got := machineToInstanceSpec(tt.openStackCluster(), tt.machine(), tt.openStackMachine(), "user-data") - Expect(got).To(Equal(tt.wantInstanceSpec())) + g := NewGomegaWithT(t) + log := testr.New(t) + + mockCtrl := gomock.NewController(t) + mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "") + + reconciler := OpenStackMachineReconciler{} + + computeRecorder := mockScopeFactory.ComputeClient.EXPECT() + imageRecorder := mockScopeFactory.ImageClient.EXPECT() + networkRecorder := mockScopeFactory.NetworkClient.EXPECT() + volumeRecorder := mockScopeFactory.VolumeClient.EXPECT() + + if tt.expect != nil { + tt.expect(&recorders{computeRecorder, imageRecorder, networkRecorder, volumeRecorder}) + } + scopeWithLogger := scope.NewWithLogger(mockScopeFactory, log) + + openStackCluster := infrav1.OpenStackCluster{} + openStackCluster.Status.Ready = !tt.clusterNotReady + openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{ + NetworkStatus: infrav1.NetworkStatus{ + Name: "my-network", + ID: networkUUID, + }, + Subnets: []infrav1.Subnet{ + { + Name: "my-subnet", + ID: subnetUUID, + CIDR: "192.168.0.0/24", + }, + }, + } + + machine := clusterv1.Machine{} + + osMachine := &tt.osMachine + osMachine.Name = openStackMachineName + osMachine.Finalizers = []string{infrav1.MachineFinalizer} + + _, err := reconciler.reconcileDelete(scopeWithLogger, openStackMachineName, &openStackCluster, &machine, &tt.osMachine) + + if tt.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).ToNot(HaveOccurred()) + } + + if tt.wantRemoveFinalizer { + g.Expect(osMachine.Finalizers).To(BeEmpty()) + } else { + g.Expect(osMachine.Finalizers).To(ConsistOf(infrav1.MachineFinalizer)) + } }) } } diff --git a/controllers/suite_test.go b/controllers/suite_test.go index b0edc98d5f..d4497275b7 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -22,7 +22,6 @@ import ( "path/filepath" "testing" - "github.com/go-logr/logr" "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -32,12 +31,14 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" + "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7" + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute" "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope" "sigs.k8s.io/cluster-api-provider-openstack/test/helpers/external" @@ -125,8 +126,9 @@ var _ = Describe("EnvTest sanity check", func() { }) var _ = Describe("When calling getOrCreate", func() { + logger := GinkgoLogr + var ( - logger logr.Logger reconsiler OpenStackMachineReconciler mockCtrl *gomock.Controller mockScopeFactory *scope.MockScopeFactory @@ -136,22 +138,24 @@ var _ = Describe("When calling getOrCreate", func() { BeforeEach(func() { ctx = context.Background() - logger = logr.Discard() reconsiler = OpenStackMachineReconciler{} mockCtrl = gomock.NewController(GinkgoT()) - mockScopeFactory = scope.NewMockScopeFactory(mockCtrl, "1234", logger) - computeService, err = compute.NewService(mockScopeFactory) + mockScopeFactory = scope.NewMockScopeFactory(mockCtrl, "1234") + computeService, err = compute.NewService(scope.NewWithLogger(mockScopeFactory, logger)) Expect(err).NotTo(HaveOccurred()) }) It("should return an error if unable to get instance", func() { - cluster := &clusterv1.Cluster{} openStackCluster := &infrav1.OpenStackCluster{} machine := &clusterv1.Machine{} - openStackMachine := &infrav1.OpenStackMachine{} + openStackMachine := &infrav1.OpenStackMachine{ + Status: infrav1.OpenStackMachineStatus{ + InstanceID: ptr.To("machine-uuid"), + }, + } - mockScopeFactory.ComputeClient.EXPECT().ListServers(gomock.Any()).Return(nil, errors.New("Test error when listing servers")) - instanceStatus, err := reconsiler.getOrCreate(logger, cluster, openStackCluster, machine, openStackMachine, computeService, "") + mockScopeFactory.ComputeClient.EXPECT().GetServer(gomock.Any()).Return(nil, errors.New("Test error when getting server")) + instanceStatus, err := reconsiler.getOrCreateInstance(logger, openStackCluster, machine, openStackMachine, computeService, "", []string{}) Expect(err).To(HaveOccurred()) Expect(instanceStatus).To(BeNil()) conditions := openStackMachine.GetConditions() @@ -163,4 +167,18 @@ var _ = Describe("When calling getOrCreate", func() { } } }) + + It("should retrieve instance by name if no ID is stored", func() { + openStackCluster := &infrav1.OpenStackCluster{} + machine := &clusterv1.Machine{} + openStackMachine := &infrav1.OpenStackMachine{} + servers := make([]clients.ServerExt, 1) + servers[0].ID = "machine-uuid" + + mockScopeFactory.ComputeClient.EXPECT().ListServers(gomock.Any()).Return(servers, nil) + instanceStatus, err := reconsiler.getOrCreateInstance(logger, openStackCluster, machine, openStackMachine, computeService, "", []string{}) + Expect(err).ToNot(HaveOccurred()) + Expect(instanceStatus).ToNot(BeNil()) + Expect(instanceStatus.ID()).To(Equal("machine-uuid")) + }) }) diff --git a/docs/book/gen-crd-api-reference-docs/config.json b/docs/book/gen-crd-api-reference-docs/config.json new file mode 100644 index 0000000000..840ab6b56d --- /dev/null +++ b/docs/book/gen-crd-api-reference-docs/config.json @@ -0,0 +1,36 @@ +{ + "hideMemberFields": [ + "TypeMeta" + ], + "hideTypePatterns": [ + "ParseError$", + "List$" + ], + "externalPackages": [ + { + "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Duration$", + "docsURLTemplate": "https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration" + }, + { + "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Condition$", + "docsURLTemplate": "https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Condition" + }, + { + "typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api/api/v1beta1", + "docsURLTemplate": "https://doc.crds.dev/github.com/kubernetes-sigs/cluster-api@v1.6.0" + }, + { + "typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api/errors", + "docsURLTemplate": "https://pkg.go.dev/sigs.k8s.io/cluster-api@v1.5.1/errors#{{.TypeIdentifier}}" + }, + { + "typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api-provider-openstack/api/v1beta1", + "docsURLTemplate": "https://cluster-api-openstack.sigs.k8s.io/api/v1beta1/api#infrastructure.cluster.x-k8s.io/v1beta1.{{.TypeIdentifier}}" + } + ], + "typeDisplayNamePrefixOverrides": { + "k8s.io/api/": "Kubernetes ", + "k8s.io/apimachinery/pkg/apis/": "Kubernetes " + }, + "markdownDisabled": false + } diff --git a/docs/book/gen-crd-api-reference-docs/template/members.tpl b/docs/book/gen-crd-api-reference-docs/template/members.tpl new file mode 100644 index 0000000000..448ce2fb04 --- /dev/null +++ b/docs/book/gen-crd-api-reference-docs/template/members.tpl @@ -0,0 +1,48 @@ +{{ define "members" }} + +{{ range .Members }} +{{ if not (hiddenMember .)}} +
{{ fieldName . }}
+ (Members of {{ fieldName . }} are embedded into this type.)
+
metadata field.
+ {{ end }}
+
+ {{ if or (eq (fieldName .) "spec") }}
+ + {{ safe (renderComments .) }} +
+ {{ end }} + {{ end }} + + Resource Types: +
+ Generated with gen-crd-api-reference-docs.
+
{{.Underlying}} alias){{ end -}}
++ (Appears on: + {{- $prev := "" -}} + {{- range . -}} + {{- if $prev -}}, {{ end -}} + {{ $prev = . }} + {{ typeDisplayName . }} + {{- end -}} + ) +
+{{ end }} + ++ {{ safe (renderComments .CommentLines) }} +
+ +{{ with (constantsOfType .) }} +| Value | +Description | +
|---|---|
{{ typeDisplayName . }} |
+ {{ safe (renderComments .CommentLines) }} | +
| Field | +Description | +
|---|---|
+ apiVersion+ string |
+
+
+ {{apiGroup .}}
+
+ |
+
+ kind+ string + |
+ {{.Name.Name}} |
+
+
package v1alpha1 contains API Schema definitions for the infrastructure v1alpha1 API group
+ +Resource Types: ++
OpenStackFloatingIPPool is the Schema for the openstackfloatingippools API.
+ +| Field | +Description | +||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||
+spec+ + +OpenStackFloatingIPPoolSpec + + + |
+
+ + +
|
+||||||||||
+status+ + +OpenStackFloatingIPPoolStatus + + + |
++ | +
+(Appears on: +OpenStackFloatingIPPool) +
++
OpenStackFloatingIPPoolSpec defines the desired state of OpenStackFloatingIPPool.
+ +| Field | +Description | +
|---|---|
+preAllocatedFloatingIPs+ +[]string + + |
+
+ PreAllocatedFloatingIPs is a list of floating IPs precreated in OpenStack that should be used by this pool. +These are used before allocating new ones and are not deleted from OpenStack when the pool is deleted. + |
+
+maxIPs+ +int + + |
+
+(Optional)
+ MaxIPs is the maximum number of floating ips that can be allocated from this pool, if nil there is no limit. +If set, the pool will stop allocating floating ips when it reaches this number of ClaimedIPs. + |
+
+identityRef+ + +sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference + + + |
+
+ IdentityRef is a reference to a identity to be used when reconciling this pool. + |
+
+floatingIPNetwork+ + +sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkParam + + + |
+
+(Optional)
+ FloatingIPNetwork is the external network to use for floating ips, if there’s only one external network it will be used by default + |
+
+reclaimPolicy+ + +ReclaimPolicy + + + |
+
+ The stratergy to use for reclaiming floating ips when they are released from a machine + |
+
+(Appears on: +OpenStackFloatingIPPool) +
++
OpenStackFloatingIPPoolStatus defines the observed state of OpenStackFloatingIPPool.
+ +| Field | +Description | +
|---|---|
+claimedIPs+ +[]string + + |
++(Optional) + | +
+availableIPs+ +[]string + + |
++(Optional) + | +
+failedIPs+ +[]string + + |
+
+(Optional)
+ FailedIPs contains a list of floating ips that failed to be allocated + |
+
+floatingIPNetwork+ + +sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkStatus + + + |
+
+(Optional)
+ floatingIPNetwork contains information about the network used for floating ips + |
+
+conditions+ + +sigs.k8s.io/cluster-api/api/v1beta1.Conditions + + + |
++ | +
string alias)+(Appears on: +OpenStackFloatingIPPoolSpec) +
++
ReclaimPolicy is a string type alias to represent reclaim policies for floating ips.
+ +| Value | +Description | +
|---|---|
"Delete" |
+ReclaimDelete is the reclaim policy for floating ips. + |
+
"Retain" |
+ReclaimRetain is the reclaim policy for floating ips. + |
+
+Generated with gen-crd-api-reference-docs.
+
+
Package v1alpha6 contains API Schema definitions for the infrastructure v1alpha6 API group.
+ +Resource Types: + ++
OpenStackCluster is the Schema for the openstackclusters API.
+Deprecated: This type will be removed in one of the next releases.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha6
+
+ |
+||||||||||||||||||||||||||||||||||||||||||
+kind+string + |
+OpenStackCluster |
+||||||||||||||||||||||||||||||||||||||||||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||||||||||||||||||||||||||||||||
+spec+ + +OpenStackClusterSpec + + + |
+
+ + +
|
+||||||||||||||||||||||||||||||||||||||||||
+status+ + +OpenStackClusterStatus + + + |
++ | +
+
OpenStackClusterTemplate is the Schema for the openstackclustertemplates API.
+Deprecated: This type will be removed in one of the next releases.
+ +| Field | +Description | +||
|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha6
+
+ |
+||
+kind+string + |
+OpenStackClusterTemplate |
+||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||
+spec+ + +OpenStackClusterTemplateSpec + + + |
+
+ + +
|
+
+
OpenStackMachine is the Schema for the openstackmachines API.
+Deprecated: This type will be removed in one of the next releases.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha6
+
+ |
+||||||||||||||||||||||||||||||||||||||
+kind+string + |
+OpenStackMachine |
+||||||||||||||||||||||||||||||||||||||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||||||||||||||||||||||||||||
+spec+ + +OpenStackMachineSpec + + + |
+
+ + +
|
+||||||||||||||||||||||||||||||||||||||
+status+ + +OpenStackMachineStatus + + + |
++ | +
+
OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API.
+Deprecated: This type will be removed in one of the next releases.
+ +| Field | +Description | +||
|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha6
+
+ |
+||
+kind+string + |
+OpenStackMachineTemplate |
+||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||
+spec+ + +OpenStackMachineTemplateSpec + + + |
+
+ + +
|
+
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+enabled+ +bool + + |
+
+ Enabled defines whether a load balancer should be created. + |
+
+additionalPorts+ +[]int + + |
+
+ AdditionalPorts adds additional tcp ports to the load balancer. + |
+
+allowedCidrs+ +[]string + + |
+
+ AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs. + |
+
+provider+ +string + + |
+
+ Octavia Provider Used to create load balancer + |
+
+(Appears on: +PortOpts) +
++
+| Field | +Description | +
|---|---|
+ipAddress+ +string + + |
++ | +
+macAddress+ +string + + |
++ | +
+(Appears on: +OpenStackClusterSpec) +
++
Bastion represents basic information about the bastion node.
+ +| Field | +Description | +
|---|---|
+enabled+ +bool + + |
++(Optional) + | +
+instance+ + +OpenStackMachineSpec + + + |
+
+ Instance for the bastion itself + |
+
+availabilityZone+ +string + + |
++(Optional) + | +
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+fixedIP+ +string + + |
+
+ The FixedIP in the corresponding subnet + |
+
+subnet+ + +SubnetParam + + + |
+
+ The subnet in which the FixedIP is used for the Gateway of this router + |
+
+(Appears on: +PortOpts) +
++
+| Field | +Description | +
|---|---|
+subnet+ + +SubnetFilter + + + |
+
+ Subnet is an openstack subnet query that will return the id of a subnet to create +the fixed IP of a port in. This query must not return more than one subnet. + |
+
+ipAddress+ +string + + |
++ | +
+(Appears on: +OpenStackClusterStatus) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
++ | +
+name+ +string + + |
++ | +
+trunk+ +bool + + |
++ | +
+failureDomain+ +string + + |
++ | +
+securigyGroups+ +[]string + + |
++ | +
+networks+ + +[]Network + + + |
++ | +
+subnet+ +string + + |
++ | +
+tags+ +[]string + + |
++ | +
+image+ +string + + |
++ | +
+imageUUID+ +string + + |
++ | +
+flavor+ +string + + |
++ | +
+sshKeyName+ +string + + |
++ | +
+userData+ +string + + |
++ | +
+metadata+ +map[string]string + + |
++ | +
+configDrive+ +bool + + |
++ | +
+rootVolume+ + +RootVolume + + + |
++ | +
+serverGroupID+ +string + + |
++ | +
+state+ + +InstanceState + + + |
++ | +
+ip+ +string + + |
++ | +
+floatingIP+ +string + + |
++ | +
string alias)+(Appears on: +Instance, +OpenStackMachineStatus) +
++
InstanceState describes the state of an OpenStack instance.
+ ++(Appears on: +Network) +
++
LoadBalancer represents basic information about the associated OpenStack LoadBalancer.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+ip+ +string + + |
++ | +
+internalIP+ +string + + |
++ | +
+allowedCIDRs+ +[]string + + |
++(Optional) + | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +Instance, +OpenStackClusterStatus) +
++
Network represents basic information about an OpenStack Neutron Network associated with an instance’s port.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+subnet+ + +Subnet + + + |
++ | +
+port+ + +PortOpts + + + |
++ | +
+router+ + +Router + + + |
++ | +
+apiServerLoadBalancer+ + +LoadBalancer + + + |
+
+ Be careful when using APIServerLoadBalancer, because this field is optional and therefore not +set in all cases + |
+
+(Appears on: +NetworkParam, +OpenStackClusterSpec, +PortOpts) +
++
+| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+uuid+ +string + + |
+
+ Optional UUID of the network.
+If specified this will not be validated prior to server creation.
+Required if |
+
+fixedIP+ +string + + |
+
+ A fixed IPv4 address for the NIC. + |
+
+filter+ + +NetworkFilter + + + |
+
+ Filters for optional network query + |
+
+subnets+ + +[]SubnetParam + + + |
+
+ Subnet within a network to use + |
+
+(Appears on: +OpenStackCluster, +OpenStackClusterTemplateResource) +
++
OpenStackClusterSpec defines the desired state of OpenStackCluster.
+ +| Field | +Description | +
|---|---|
+cloudName+ +string + + |
+
+(Optional)
+ The name of the cloud to use from the clouds secret + |
+
+nodeCidr+ +string + + |
+
+ NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a +network, a subnet with NodeCIDR, and a router connected to this subnet. +If you leave this empty, no network will be created. + |
+
+network+ + +NetworkFilter + + + |
+
+ If NodeCIDR cannot be set this can be used to detect an existing network. + |
+
+subnet+ + +SubnetFilter + + + |
+
+ If NodeCIDR cannot be set this can be used to detect an existing subnet. + |
+
+dnsNameservers+ +[]string + + |
+
+ DNSNameservers is the list of nameservers for OpenStack Subnet being created. +Set this value when you need create a new network/subnet while the access +through DNS is required. + |
+
+externalRouterIPs+ + +[]ExternalRouterIPParam + + + |
+
+ ExternalRouterIPs is an array of externalIPs on the respective subnets. +This is necessary if the router needs a fixed ip in a specific subnet. + |
+
+externalNetworkId+ +string + + |
+
+(Optional)
+ ExternalNetworkID is the ID of an external OpenStack Network. This is necessary +to get public internet to the VMs. + |
+
+apiServerLoadBalancer+ + +APIServerLoadBalancer + + + |
+
+(Optional)
+ APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
+It must be activated by setting |
+
+disableAPIServerFloatingIP+ +bool + + |
+
+(Optional)
+ DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating +IP to the API server. This allows for the creation of clusters when attaching a floating +IP to the API server (and hence, in many cases, exposing the API server to the internet) +is not possible or desirable, e.g. if using a shared VLAN for communication between +management and workload clusters or when the management cluster is inside the +project network. +This option requires that the API server use a VIP on the cluster network so that the +underlying machines can change without changing ControlPlaneEndpoint.Host. +When using a managed load balancer, this VIP will be managed automatically. +If not using a managed load balancer, cluster configuration will fail without additional +configuration to manage the VIP on the control plane machines, which falls outside of +the scope of this controller. + |
+
+apiServerFloatingIP+ +string + + |
+
+ APIServerFloatingIP is the floatingIP which will be associated with the API server. +The floatingIP will be created if it does not already exist. +If not specified, a new floatingIP is allocated. +This field is not used if DisableAPIServerFloatingIP is set to true. + |
+
+apiServerFixedIP+ +string + + |
+
+ APIServerFixedIP is the fixed IP which will be associated with the API server. +In the case where the API server has a floating IP but not a managed load balancer, +this field is not used. +If a managed load balancer is used and this field is not specified, a fixed IP will +be dynamically allocated for the load balancer. +If a managed load balancer is not used AND the API server floating IP is disabled, +this field MUST be specified and should correspond to a pre-allocated port that +holds the fixed IP to be used as a VIP. + |
+
+apiServerPort+ +int + + |
+
+ APIServerPort is the port on which the listener on the APIServer +will be created + |
+
+managedSecurityGroups+ +bool + + |
+
+(Optional)
+ ManagedSecurityGroups determines whether OpenStack security groups for the cluster +will be managed by the OpenStack provider or whether pre-existing security groups will +be specified as part of the configuration. +By default, the managed security groups have rules that allow the Kubelet, etcd, the +Kubernetes API server and the Calico CNI plugin to function correctly. + |
+
+allowAllInClusterTraffic+ +bool + + |
+
+(Optional)
+ AllowAllInClusterTraffic is only used when managed security groups are in use. +If set to true, the rules for the managed security groups are configured so that all +ingress and egress between cluster nodes is permitted, allowing CNIs other than +Calico to be used. + |
+
+disablePortSecurity+ +bool + + |
+
+ DisablePortSecurity disables the port security of the network created for the +Kubernetes cluster, which also disables SecurityGroups + |
+
+tags+ +[]string + + |
+
+ Tags for all resources in cluster + |
+
+controlPlaneEndpoint+ + +sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint + + + |
+
+(Optional)
+ ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. + |
+
+controlPlaneAvailabilityZones+ +[]string + + |
+
+ ControlPlaneAvailabilityZones is the az to deploy control plane to + |
+
+controlPlaneOmitAvailabilityZone+ +bool + + |
+
+ Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler +to make a decision on which az to use based on other scheduling constraints + |
+
+bastion+ + +Bastion + + + |
+
+(Optional)
+ Bastion is the OpenStack instance to login the nodes +As a rolling update is not ideal during a bastion host session, we
+prevent changes to a running bastion configuration. Set |
+
+identityRef+ + +OpenStackIdentityReference + + + |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster + |
+
+(Appears on: +OpenStackCluster) +
++
OpenStackClusterStatus defines the observed state of OpenStackCluster.
+ +| Field | +Description | +
|---|---|
+ready+ +bool + + |
++ | +
+network+ + +Network + + + |
+
+ Network contains all information about the created OpenStack Network. +It includes Subnets and Router. + |
+
+externalNetwork+ + +Network + + + |
+
+ External Network contains information about the created OpenStack external network. + |
+
+failureDomains+ + +sigs.k8s.io/cluster-api/api/v1beta1.FailureDomains + + + |
+
+ FailureDomains represent OpenStack availability zones + |
+
+controlPlaneSecurityGroup+ + +SecurityGroup + + + |
+
+ ControlPlaneSecurityGroups contains all the information about the OpenStack +Security Group that needs to be applied to control plane nodes. +TODO: Maybe instead of two properties, we add a property to the group? + |
+
+workerSecurityGroup+ + +SecurityGroup + + + |
+
+ WorkerSecurityGroup contains all the information about the OpenStack Security +Group that needs to be applied to worker nodes. + |
+
+bastionSecurityGroup+ + +SecurityGroup + + + |
++ | +
+bastion+ + +Instance + + + |
++ | +
+failureReason+ + +sigs.k8s.io/cluster-api/errors.ClusterStatusError + + + |
+
+(Optional)
+ FailureReason will be set in the event that there is a terminal problem +reconciling the OpenStackCluster and will contain a succinct value suitable +for machine interpretation. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the OpenStackCluster’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of +OpenStackClusters can be added as events to the OpenStackCluster object +and/or logged in the controller’s output. + |
+
+failureMessage+ +string + + |
+
+(Optional)
+ FailureMessage will be set in the event that there is a terminal problem +reconciling the OpenStackCluster and will contain a more verbose string suitable +for logging and human consumption. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the OpenStackCluster’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of +OpenStackClusters can be added as events to the OpenStackCluster object +and/or logged in the controller’s output. + |
+
+(Appears on: +OpenStackClusterTemplateSpec) +
++
OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+spec+ + +OpenStackClusterSpec + + + |
+
+ + +
|
+
+(Appears on: +OpenStackClusterTemplate) +
++
OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+ +| Field | +Description | +
|---|---|
+template+ + +OpenStackClusterTemplateResource + + + |
++ | +
+(Appears on: +OpenStackClusterSpec, +OpenStackMachineSpec) +
++
OpenStackIdentityReference is a reference to an infrastructure +provider identity to be used to provision cluster resources.
+ +| Field | +Description | +
|---|---|
+kind+ +string + + |
+
+ Kind of the identity. Must be supported by the infrastructure +provider and may be either cluster or namespace-scoped. + |
+
+name+ +string + + |
+
+ Name of the infrastructure identity to be used. +Must be either a cluster-scoped resource, or namespaced-scoped +resource the same namespace as the resource(s) being provisioned. + |
+
+(Appears on: +OpenStackMachine, +Bastion, +OpenStackMachineTemplateResource) +
++
OpenStackMachineSpec defines the desired state of OpenStackMachine.
+ +| Field | +Description | +
|---|---|
+providerID+ +string + + |
+
+ ProviderID is the unique identifier as specified by the cloud provider. + |
+
+instanceID+ +string + + |
+
+ InstanceID is the OpenStack instance ID for this machine. + |
+
+cloudName+ +string + + |
+
+(Optional)
+ The name of the cloud to use from the clouds secret + |
+
+flavor+ +string + + |
+
+ The flavor reference for the flavor for your server instance. + |
+
+image+ +string + + |
+
+ The name of the image to use for your server instance. +If the RootVolume is specified, this will be ignored and use rootVolume directly. + |
+
+imageUUID+ +string + + |
+
+ The uuid of the image to use for your server instance. +if it’s empty, Image name will be used + |
+
+sshKeyName+ +string + + |
+
+ The ssh key to inject in the instance + |
+
+networks+ + +[]NetworkParam + + + |
+
+ A networks object. Required parameter when there are multiple networks defined for the tenant. +When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. + |
+
+ports+ + +[]PortOpts + + + |
+
+ Ports to be attached to the server instance. They are created if a port with the given name does not already exist. +When you do not specify both networks and ports parameters, the server attaches to the only network created for the current tenant. + |
+
+subnet+ +string + + |
+
+ UUID, IP address of a port from this subnet will be marked as AccessIPv4 on the created compute instance + |
+
+floatingIP+ +string + + |
+
+ The floatingIP which will be associated to the machine, only used for master. +The floatingIP should have been created and haven’t been associated. + |
+
+securityGroups+ + +[]SecurityGroupParam + + + |
+
+ The names of the security groups to assign to the instance + |
+
+trunk+ +bool + + |
+
+ Whether the server instance is created on a trunk port or not. + |
+
+tags+ +[]string + + |
+
+ Machine tags +Requires Nova api 2.52 minimum! + |
+
+serverMetadata+ +map[string]string + + |
+
+ Metadata mapping. Allows you to create a map of key value pairs to add to the server instance. + |
+
+configDrive+ +bool + + |
+
+ Config Drive support + |
+
+rootVolume+ + +RootVolume + + + |
+
+ The volume metadata to boot from + |
+
+serverGroupID+ +string + + |
+
+ The server group to assign the machine to + |
+
+identityRef+ + +OpenStackIdentityReference + + + |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster + |
+
+(Appears on: +OpenStackMachine) +
++
OpenStackMachineStatus defines the observed state of OpenStackMachine.
+ +| Field | +Description | +
|---|---|
+ready+ +bool + + |
+
+(Optional)
+ Ready is true when the provider resource is ready. + |
+
+addresses+ +[]Kubernetes core/v1.NodeAddress + + |
+
+ Addresses contains the OpenStack instance associated addresses. + |
+
+instanceState+ + +InstanceState + + + |
+
+(Optional)
+ InstanceState is the state of the OpenStack instance for this machine. + |
+
+failureReason+ + +sigs.k8s.io/cluster-api/errors.MachineStatusError + + + |
++ | +
+failureMessage+ +string + + |
+
+(Optional)
+ FailureMessage will be set in the event that there is a terminal problem +reconciling the Machine and will contain a more verbose string suitable +for logging and human consumption. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the Machine’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of Machines +can be added as events to the Machine object and/or logged in the +controller’s output. + |
+
+conditions+ + +sigs.k8s.io/cluster-api/api/v1beta1.Conditions + + + |
++ | +
+(Appears on: +OpenStackMachineTemplateSpec) +
++
OpenStackMachineTemplateResource describes the data needed to create a OpenStackMachine from a template.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+spec+ + +OpenStackMachineSpec + + + |
+
+ Spec is the specification of the desired behavior of the machine. ++ +
|
+
+(Appears on: +OpenStackMachineTemplate) +
++
OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+ +| Field | +Description | +
|---|---|
+template+ + +OpenStackMachineTemplateResource + + + |
++ | +
+(Appears on: +Network, +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+network+ + +NetworkFilter + + + |
+
+ Network is a query for an openstack network that the port will be created or discovered on. +This will fail if the query returns more than one network. + |
+
+nameSuffix+ +string + + |
+
+ Used to make the name of the port unique. If unspecified, instead the 0-based index of the port in the list is used. + |
+
+description+ +string + + |
++ | +
+adminStateUp+ +bool + + |
++ | +
+macAddress+ +string + + |
++ | +
+fixedIPs+ + +[]FixedIP + + + |
+
+ Specify pairs of subnet and/or IP address. These should be subnets of the network with the given NetworkID. + |
+
+tenantId+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+securityGroups+ +[]string + + |
+
+ The uuids of the security groups to assign to the instance + |
+
+securityGroupFilters+ + +[]SecurityGroupParam + + + |
+
+ The names, uuids, filters or any combination these of the security groups to assign to the instance + |
+
+allowedAddressPairs+ + +[]AddressPair + + + |
++ | +
+trunk+ +bool + + |
+
+ Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited. + |
+
+hostId+ +string + + |
+
+ The ID of the host where the port is allocated + |
+
+vnicType+ +string + + |
+
+ The virtual network interface card (vNIC) type that is bound to the neutron port. + |
+
+profile+ +map[string]string + + |
+
+ A dictionary that enables the application running on the specified +host to pass and receive virtual network interface (VIF) port-specific +information to the plug-in. + |
+
+disablePortSecurity+ +bool + + |
+
+ DisablePortSecurity enables or disables the port security when set. +When not set, it takes the value of the corresponding field at the network level. + |
+
+tags+ +[]string + + |
+
+ Tags applied to the port (and corresponding trunk, if a trunk is configured.) +These tags are applied in addition to the instance’s tags, which will also be applied to the port. + |
+
+valueSpecs+ + +[]ValueSpec + + + |
+
+(Optional)
+ Value specs are extra parameters to include in the API request with OpenStack. +This is an extension point for the API, so what they do and if they are supported, +depends on the specific OpenStack implementation. + |
+
+(Appears on: +Instance, +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+diskSize+ +int + + |
++ | +
+volumeType+ +string + + |
++ | +
+availabilityZone+ +string + + |
++ | +
+(Appears on: +Network) +
++
Router represents basic information about the associated OpenStack Neutron Router.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+ips+ +[]string + + |
++(Optional) + | +
+(Appears on: +OpenStackClusterStatus) +
++
SecurityGroup represents the basic information of the associated +OpenStack Neutron Security Group.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+rules+ + +[]SecurityGroupRule + + + |
++ | +
+(Appears on: +SecurityGroupParam) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
++ | +
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+tenantId+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+limit+ +int + + |
++ | +
+marker+ +string + + |
++ | +
+sortKey+ +string + + |
++ | +
+sortDir+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +OpenStackMachineSpec, +PortOpts) +
++
+| Field | +Description | +
|---|---|
+uuid+ +string + + |
+
+ Security Group UID + |
+
+name+ +string + + |
+
+ Security Group name + |
+
+filter+ + +SecurityGroupFilter + + + |
+
+ Filters used to query security groups in openstack + |
+
+(Appears on: +SecurityGroup) +
++
SecurityGroupRule represent the basic information of the associated OpenStack +Security Group Role.
+ +| Field | +Description | +
|---|---|
+description+ +string + + |
++ | +
+name+ +string + + |
++ | +
+direction+ +string + + |
++ | +
+etherType+ +string + + |
++ | +
+securityGroupID+ +string + + |
++ | +
+portRangeMin+ +int + + |
++ | +
+portRangeMax+ +int + + |
++ | +
+protocol+ +string + + |
++ | +
+remoteGroupID+ +string + + |
++ | +
+remoteIPPrefix+ +string + + |
++ | +
+(Appears on: +Network) +
++
Subnet represents basic information about the associated OpenStack Neutron Subnet.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+cidr+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +FixedIP, +OpenStackClusterSpec, +SubnetParam) +
++
+| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+ipVersion+ +int + + |
++ | +
+gateway_ip+ +string + + |
++ | +
+cidr+ +string + + |
++ | +
+ipv6AddressMode+ +string + + |
++ | +
+ipv6RaMode+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +ExternalRouterIPParam, +NetworkParam) +
++
+| Field | +Description | +
|---|---|
+uuid+ +string + + |
+
+ Optional UUID of the subnet.
+If specified this will not be validated prior to server creation.
+If specified, the enclosing |
+
+filter+ + +SubnetFilter + + + |
+
+ Filters for optional subnet query + |
+
+(Appears on: +PortOpts) +
++
ValueSpec represents a single value_spec key-value pair.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name is the name of the key-value pair. +This is just for identifying the pair and will not be sent to the OpenStack API. + |
+
+key+ +string + + |
+
+ Key is the key in the key-value pair. + |
+
+value+ +string + + |
+
+ Value is the value in the key-value pair. + |
+
+Generated with gen-crd-api-reference-docs.
+
+
Package v1alpha7 contains API Schema definitions for the infrastructure v1alpha7 API group.
+ +Resource Types: + ++
OpenStackCluster is the Schema for the openstackclusters API.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha7
+
+ |
+||||||||||||||||||||||||||||||||||||||||||||||
+kind+string + |
+OpenStackCluster |
+||||||||||||||||||||||||||||||||||||||||||||||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||||||||||||||||||||||||||||||||||||
+spec+ + +OpenStackClusterSpec + + + |
+
+ + +
|
+||||||||||||||||||||||||||||||||||||||||||||||
+status+ + +OpenStackClusterStatus + + + |
++ | +
+
OpenStackClusterTemplate is the Schema for the openstackclustertemplates API.
+ +| Field | +Description | +||
|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha7
+
+ |
+||
+kind+string + |
+OpenStackClusterTemplate |
+||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||
+spec+ + +OpenStackClusterTemplateSpec + + + |
+
+ + +
|
+
+
OpenStackMachine is the Schema for the openstackmachines API.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha7
+
+ |
+||||||||||||||||||||||||||||||||||||
+kind+string + |
+OpenStackMachine |
+||||||||||||||||||||||||||||||||||||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||||||||||||||||||||||||||
+spec+ + +OpenStackMachineSpec + + + |
+
+ + +
|
+||||||||||||||||||||||||||||||||||||
+status+ + +OpenStackMachineStatus + + + |
++ | +
+
OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API.
+ +| Field | +Description | +||
|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1alpha7
+
+ |
+||
+kind+string + |
+OpenStackMachineTemplate |
+||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||
+spec+ + +OpenStackMachineTemplateSpec + + + |
+
+ + +
|
+
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+enabled+ +bool + + |
+
+ Enabled defines whether a load balancer should be created. + |
+
+additionalPorts+ +[]int + + |
+
+ AdditionalPorts adds additional tcp ports to the load balancer. + |
+
+allowedCidrs+ +[]string + + |
+
+ AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs. + |
+
+provider+ +string + + |
+
+ Octavia Provider Used to create load balancer + |
+
+(Appears on: +OpenStackMachineSpec) +
++
AdditionalBlockDevice is a block device to attach to the server.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name of the block device in the context of a machine. +If the block device is a volume, the Cinder volume will be named +as a combination of the machine name and this name. +Also, this name will be used for tagging the block device. +Information about the block device tag can be obtained from the OpenStack +metadata API or the config drive. + |
+
+sizeGiB+ +int + + |
+
+ SizeGiB is the size of the block device in gibibytes (GiB). + |
+
+storage+ + +BlockDeviceStorage + + + |
+
+ Storage specifies the storage type of the block device and +additional storage options. + |
+
+(Appears on: +PortOpts) +
++
+| Field | +Description | +
|---|---|
+ipAddress+ +string + + |
++ | +
+macAddress+ +string + + |
++ | +
+(Appears on: +OpenStackClusterSpec) +
++
Bastion represents basic information about the bastion node.
+ +| Field | +Description | +
|---|---|
+enabled+ +bool + + |
++(Optional) + | +
+instance+ + +OpenStackMachineSpec + + + |
+
+ Instance for the bastion itself + |
+
+availabilityZone+ +string + + |
++(Optional) + | +
+(Appears on: +OpenStackClusterStatus) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
++ | +
+name+ +string + + |
++ | +
+sshKeyName+ +string + + |
++ | +
+state+ + +InstanceState + + + |
++ | +
+ip+ +string + + |
++ | +
+floatingIP+ +string + + |
++ | +
+(Appears on: +PortOpts) +
++
+| Field | +Description | +
|---|---|
+ovsHWOffload+ +bool + + |
+
+ OVSHWOffload enables or disables the OVS hardware offload feature. + |
+
+trustedVF+ +bool + + |
+
+ TrustedVF enables or disables the “trusted mode” for the VF. + |
+
+(Appears on: +AdditionalBlockDevice) +
++
BlockDeviceStorage is the storage type of a block device to create and +contains additional storage options.
+ +| Field | +Description | +
|---|---|
+type+ + +BlockDeviceType + + + |
+
+ Type is the type of block device to create. +This can be either “Volume” or “Local”. + |
+
+volume+ + +BlockDeviceVolume + + + |
+
+(Optional)
+ Volume contains additional storage options for a volume block device. + |
+
string alias)+(Appears on: +BlockDeviceStorage) +
++
BlockDeviceType defines the type of block device to create.
+ +| Value | +Description | +
|---|---|
"Local" |
+LocalBlockDevice is an ephemeral block device attached to the server. + |
+
"Volume" |
+VolumeBlockDevice is a volume block device attached to the server. + |
+
+(Appears on: +BlockDeviceStorage) +
++
BlockDeviceVolume contains additional storage options for a volume block device.
+ +| Field | +Description | +
|---|---|
+type+ +string + + |
+
+(Optional)
+ Type is the Cinder volume type of the volume. +If omitted, the default Cinder volume type that is configured in the OpenStack cloud +will be used. + |
+
+availabilityZone+ +string + + |
+
+(Optional)
+ AvailabilityZone is the volume availability zone to create the volume in. +If omitted, the availability zone of the server will be used. +The availability zone must NOT contain spaces otherwise it will lead to volume that belongs +to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for +further information. + |
+
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+fixedIP+ +string + + |
+
+ The FixedIP in the corresponding subnet + |
+
+subnet+ + +SubnetFilter + + + |
+
+ The subnet in which the FixedIP is used for the Gateway of this router + |
+
+(Appears on: +PortOpts) +
++
+| Field | +Description | +
|---|---|
+subnet+ + +SubnetFilter + + + |
+
+ Subnet is an openstack subnet query that will return the id of a subnet to create +the fixed IP of a port in. This query must not return more than one subnet. + |
+
+ipAddress+ +string + + |
++ | +
string alias)+(Appears on: +BastionStatus, +OpenStackMachineStatus) +
++
InstanceState describes the state of an OpenStack instance.
+ ++(Appears on: +OpenStackClusterStatus) +
++
LoadBalancer represents basic information about the associated OpenStack LoadBalancer.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+ip+ +string + + |
++ | +
+internalIP+ +string + + |
++ | +
+allowedCIDRs+ +[]string + + |
++(Optional) + | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +OpenStackClusterSpec, +PortOpts) +
++
+| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +NetworkStatusWithSubnets, +OpenStackClusterStatus) +
++
NetworkStatus contains basic information about an existing neutron network.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +OpenStackClusterStatus) +
++
NetworkStatusWithSubnets represents basic information about an existing neutron network and an associated set of subnets.
+ +| Field | +Description | +
|---|---|
+NetworkStatus+ + +NetworkStatus + + + |
+
+
+(Members of |
+
+subnets+ + +[]Subnet + + + |
+
+ Subnets is a list of subnets associated with the default cluster network. Machines which use the default cluster network will get an address from all of these subnets. + |
+
+(Appears on: +OpenStackCluster, +OpenStackClusterTemplateResource) +
++
OpenStackClusterSpec defines the desired state of OpenStackCluster.
+ +| Field | +Description | +
|---|---|
+cloudName+ +string + + |
+
+(Optional)
+ The name of the cloud to use from the clouds secret + |
+
+nodeCidr+ +string + + |
+
+ NodeCIDR is the OpenStack Subnet to be created. Cluster actuator will create a +network, a subnet with NodeCIDR, and a router connected to this subnet. +If you leave this empty, no network will be created. + |
+
+router+ + +RouterFilter + + + |
+
+(Optional)
+ If NodeCIDR is set this option can be used to detect an existing router. +If specified, no new router will be created. + |
+
+network+ + +NetworkFilter + + + |
+
+ If NodeCIDR cannot be set this can be used to detect an existing network. + |
+
+subnet+ + +SubnetFilter + + + |
+
+ If NodeCIDR cannot be set this can be used to detect an existing subnet. + |
+
+networkMtu+ +int + + |
+
+(Optional)
+ NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. +This value will be used only if the Cluster actuator creates the network. +If leaved empty, the network will have the default MTU defined in Openstack network service. +To use this field, the Openstack installation requires the net-mtu neutron API extension. + |
+
+dnsNameservers+ +[]string + + |
+
+ DNSNameservers is the list of nameservers for OpenStack Subnet being created. +Set this value when you need create a new network/subnet while the access +through DNS is required. + |
+
+externalRouterIPs+ + +[]ExternalRouterIPParam + + + |
+
+ ExternalRouterIPs is an array of externalIPs on the respective subnets. +This is necessary if the router needs a fixed ip in a specific subnet. + |
+
+externalNetworkId+ +string + + |
+
+(Optional)
+ ExternalNetworkID is the ID of an external OpenStack Network. This is necessary +to get public internet to the VMs. + |
+
+apiServerLoadBalancer+ + +APIServerLoadBalancer + + + |
+
+(Optional)
+ APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
+It must be activated by setting |
+
+disableAPIServerFloatingIP+ +bool + + |
+
+(Optional)
+ DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating +IP to the API server. This allows for the creation of clusters when attaching a floating +IP to the API server (and hence, in many cases, exposing the API server to the internet) +is not possible or desirable, e.g. if using a shared VLAN for communication between +management and workload clusters or when the management cluster is inside the +project network. +This option requires that the API server use a VIP on the cluster network so that the +underlying machines can change without changing ControlPlaneEndpoint.Host. +When using a managed load balancer, this VIP will be managed automatically. +If not using a managed load balancer, cluster configuration will fail without additional +configuration to manage the VIP on the control plane machines, which falls outside of +the scope of this controller. + |
+
+apiServerFloatingIP+ +string + + |
+
+ APIServerFloatingIP is the floatingIP which will be associated with the API server. +The floatingIP will be created if it does not already exist. +If not specified, a new floatingIP is allocated. +This field is not used if DisableAPIServerFloatingIP is set to true. + |
+
+apiServerFixedIP+ +string + + |
+
+ APIServerFixedIP is the fixed IP which will be associated with the API server. +In the case where the API server has a floating IP but not a managed load balancer, +this field is not used. +If a managed load balancer is used and this field is not specified, a fixed IP will +be dynamically allocated for the load balancer. +If a managed load balancer is not used AND the API server floating IP is disabled, +this field MUST be specified and should correspond to a pre-allocated port that +holds the fixed IP to be used as a VIP. + |
+
+apiServerPort+ +int + + |
+
+ APIServerPort is the port on which the listener on the APIServer +will be created + |
+
+managedSecurityGroups+ +bool + + |
+
+(Optional)
+ ManagedSecurityGroups determines whether OpenStack security groups for the cluster +will be managed by the OpenStack provider or whether pre-existing security groups will +be specified as part of the configuration. +By default, the managed security groups have rules that allow the Kubelet, etcd, the +Kubernetes API server and the Calico CNI plugin to function correctly. + |
+
+allowAllInClusterTraffic+ +bool + + |
+
+(Optional)
+ AllowAllInClusterTraffic is only used when managed security groups are in use. +If set to true, the rules for the managed security groups are configured so that all +ingress and egress between cluster nodes is permitted, allowing CNIs other than +Calico to be used. + |
+
+disablePortSecurity+ +bool + + |
+
+ DisablePortSecurity disables the port security of the network created for the +Kubernetes cluster, which also disables SecurityGroups + |
+
+tags+ +[]string + + |
+
+ Tags for all resources in cluster + |
+
+controlPlaneEndpoint+ + +sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint + + + |
+
+(Optional)
+ ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. + |
+
+controlPlaneAvailabilityZones+ +[]string + + |
+
+ ControlPlaneAvailabilityZones is the az to deploy control plane to + |
+
+controlPlaneOmitAvailabilityZone+ +bool + + |
+
+ Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler +to make a decision on which az to use based on other scheduling constraints + |
+
+bastion+ + +Bastion + + + |
+
+(Optional)
+ Bastion is the OpenStack instance to login the nodes +As a rolling update is not ideal during a bastion host session, we
+prevent changes to a running bastion configuration. Set |
+
+identityRef+ + +OpenStackIdentityReference + + + |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster + |
+
+(Appears on: +OpenStackCluster) +
++
OpenStackClusterStatus defines the observed state of OpenStackCluster.
+ +| Field | +Description | +
|---|---|
+ready+ +bool + + |
++ | +
+network+ + +NetworkStatusWithSubnets + + + |
+
+ Network contains information about the created OpenStack Network. + |
+
+externalNetwork+ + +NetworkStatus + + + |
+
+ externalNetwork contains information about the external network used for default ingress and egress traffic. + |
+
+router+ + +Router + + + |
+
+ Router describes the default cluster router + |
+
+apiServerLoadBalancer+ + +LoadBalancer + + + |
+
+ APIServerLoadBalancer describes the api server load balancer if one exists + |
+
+failureDomains+ + +sigs.k8s.io/cluster-api/api/v1beta1.FailureDomains + + + |
+
+ FailureDomains represent OpenStack availability zones + |
+
+controlPlaneSecurityGroup+ + +SecurityGroup + + + |
+
+ ControlPlaneSecurityGroups contains all the information about the OpenStack +Security Group that needs to be applied to control plane nodes. +TODO: Maybe instead of two properties, we add a property to the group? + |
+
+workerSecurityGroup+ + +SecurityGroup + + + |
+
+ WorkerSecurityGroup contains all the information about the OpenStack Security +Group that needs to be applied to worker nodes. + |
+
+bastionSecurityGroup+ + +SecurityGroup + + + |
++ | +
+bastion+ + +BastionStatus + + + |
++ | +
+failureReason+ + +sigs.k8s.io/cluster-api/errors.ClusterStatusError + + + |
+
+(Optional)
+ FailureReason will be set in the event that there is a terminal problem +reconciling the OpenStackCluster and will contain a succinct value suitable +for machine interpretation. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the OpenStackCluster’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of +OpenStackClusters can be added as events to the OpenStackCluster object +and/or logged in the controller’s output. + |
+
+failureMessage+ +string + + |
+
+(Optional)
+ FailureMessage will be set in the event that there is a terminal problem +reconciling the OpenStackCluster and will contain a more verbose string suitable +for logging and human consumption. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the OpenStackCluster’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of +OpenStackClusters can be added as events to the OpenStackCluster object +and/or logged in the controller’s output. + |
+
+(Appears on: +OpenStackClusterTemplateSpec) +
++
OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+spec+ + +OpenStackClusterSpec + + + |
+
+ + +
|
+
+(Appears on: +OpenStackClusterTemplate) +
++
OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+ +| Field | +Description | +
|---|---|
+template+ + +OpenStackClusterTemplateResource + + + |
++ | +
+(Appears on: +OpenStackClusterSpec, +OpenStackMachineSpec) +
++
OpenStackIdentityReference is a reference to an infrastructure +provider identity to be used to provision cluster resources.
+ +| Field | +Description | +
|---|---|
+kind+ +string + + |
+
+ Kind of the identity. Must be supported by the infrastructure +provider and may be either cluster or namespace-scoped. + |
+
+name+ +string + + |
+
+ Name of the infrastructure identity to be used. +Must be either a cluster-scoped resource, or namespaced-scoped +resource the same namespace as the resource(s) being provisioned. + |
+
+(Appears on: +OpenStackMachine, +Bastion, +OpenStackMachineTemplateResource) +
++
OpenStackMachineSpec defines the desired state of OpenStackMachine.
+ +| Field | +Description | +
|---|---|
+providerID+ +string + + |
+
+ ProviderID is the unique identifier as specified by the cloud provider. + |
+
+instanceID+ +string + + |
+
+ InstanceID is the OpenStack instance ID for this machine. + |
+
+cloudName+ +string + + |
+
+(Optional)
+ The name of the cloud to use from the clouds secret + |
+
+flavor+ +string + + |
+
+ The flavor reference for the flavor for your server instance. + |
+
+image+ +string + + |
+
+ The name of the image to use for your server instance. +If the RootVolume is specified, this will be ignored and use rootVolume directly. + |
+
+imageUUID+ +string + + |
+
+ The uuid of the image to use for your server instance. +if it’s empty, Image name will be used + |
+
+sshKeyName+ +string + + |
+
+ The ssh key to inject in the instance + |
+
+ports+ + +[]PortOpts + + + |
+
+ Ports to be attached to the server instance. They are created if a port with the given name does not already exist. +If not specified a default port will be added for the default cluster network. + |
+
+floatingIP+ +string + + |
+
+ The floatingIP which will be associated to the machine, only used for master. +The floatingIP should have been created and haven’t been associated. + |
+
+securityGroups+ + +[]SecurityGroupFilter + + + |
+
+ The names of the security groups to assign to the instance + |
+
+trunk+ +bool + + |
+
+ Whether the server instance is created on a trunk port or not. + |
+
+tags+ +[]string + + |
+
+ Machine tags +Requires Nova api 2.52 minimum! + |
+
+serverMetadata+ +map[string]string + + |
+
+ Metadata mapping. Allows you to create a map of key value pairs to add to the server instance. + |
+
+configDrive+ +bool + + |
+
+ Config Drive support + |
+
+rootVolume+ + +RootVolume + + + |
+
+ The volume metadata to boot from + |
+
+additionalBlockDevices+ + +[]AdditionalBlockDevice + + + |
+
+(Optional)
+ AdditionalBlockDevices is a list of specifications for additional block devices to attach to the server instance + |
+
+serverGroupID+ +string + + |
+
+ The server group to assign the machine to + |
+
+identityRef+ + +OpenStackIdentityReference + + + |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster. +If not specified, the identity ref of the cluster will be used instead. + |
+
+(Appears on: +OpenStackMachine) +
++
OpenStackMachineStatus defines the observed state of OpenStackMachine.
+ +| Field | +Description | +
|---|---|
+ready+ +bool + + |
+
+(Optional)
+ Ready is true when the provider resource is ready. + |
+
+addresses+ +[]Kubernetes core/v1.NodeAddress + + |
+
+ Addresses contains the OpenStack instance associated addresses. + |
+
+instanceState+ + +InstanceState + + + |
+
+(Optional)
+ InstanceState is the state of the OpenStack instance for this machine. + |
+
+failureReason+ + +sigs.k8s.io/cluster-api/errors.MachineStatusError + + + |
++ | +
+failureMessage+ +string + + |
+
+(Optional)
+ FailureMessage will be set in the event that there is a terminal problem +reconciling the Machine and will contain a more verbose string suitable +for logging and human consumption. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the Machine’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of Machines +can be added as events to the Machine object and/or logged in the +controller’s output. + |
+
+conditions+ + +sigs.k8s.io/cluster-api/api/v1beta1.Conditions + + + |
++ | +
+(Appears on: +OpenStackMachineTemplateSpec) +
++
OpenStackMachineTemplateResource describes the data needed to create a OpenStackMachine from a template.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+spec+ + +OpenStackMachineSpec + + + |
+
+ Spec is the specification of the desired behavior of the machine. ++ +
|
+
+(Appears on: +OpenStackMachineTemplate) +
++
OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+ +| Field | +Description | +
|---|---|
+template+ + +OpenStackMachineTemplateResource + + + |
++ | +
+(Appears on: +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+network+ + +NetworkFilter + + + |
+
+ Network is a query for an openstack network that the port will be created or discovered on. +This will fail if the query returns more than one network. + |
+
+nameSuffix+ +string + + |
+
+ Used to make the name of the port unique. If unspecified, instead the 0-based index of the port in the list is used. + |
+
+description+ +string + + |
++ | +
+adminStateUp+ +bool + + |
++ | +
+macAddress+ +string + + |
++ | +
+fixedIPs+ + +[]FixedIP + + + |
+
+ Specify pairs of subnet and/or IP address. These should be subnets of the network with the given NetworkID. + |
+
+securityGroupFilters+ + +[]SecurityGroupFilter + + + |
+
+ The names, uuids, filters or any combination these of the security groups to assign to the instance + |
+
+allowedAddressPairs+ + +[]AddressPair + + + |
++ | +
+trunk+ +bool + + |
+
+ Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited. + |
+
+hostId+ +string + + |
+
+ The ID of the host where the port is allocated + |
+
+vnicType+ +string + + |
+
+ The virtual network interface card (vNIC) type that is bound to the neutron port. + |
+
+profile+ + +BindingProfile + + + |
+
+ Profile is a set of key-value pairs that are used for binding details. +We intentionally don’t expose this as a map[string]string because we only want to enable +the users to set the values of the keys that are known to work in OpenStack Networking API. +See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port + |
+
+disablePortSecurity+ +bool + + |
+
+ DisablePortSecurity enables or disables the port security when set. +When not set, it takes the value of the corresponding field at the network level. + |
+
+propagateUplinkStatus+ +bool + + |
+
+ PropageteUplinkStatus enables or disables the propagate uplink status on the port. + |
+
+tags+ +[]string + + |
+
+ Tags applied to the port (and corresponding trunk, if a trunk is configured.) +These tags are applied in addition to the instance’s tags, which will also be applied to the port. + |
+
+valueSpecs+ + +[]ValueSpec + + + |
+
+(Optional)
+ Value specs are extra parameters to include in the API request with OpenStack. +This is an extension point for the API, so what they do and if they are supported, +depends on the specific OpenStack implementation. + |
+
+(Appears on: +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+diskSize+ +int + + |
++ | +
+volumeType+ +string + + |
++ | +
+availabilityZone+ +string + + |
++ | +
+(Appears on: +OpenStackClusterStatus) +
++
Router represents basic information about the associated OpenStack Neutron Router.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+ips+ +[]string + + |
++(Optional) + | +
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
++ | +
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +OpenStackClusterStatus) +
++
SecurityGroup represents the basic information of the associated +OpenStack Neutron Security Group.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+rules+ + +[]SecurityGroupRule + + + |
++ | +
+(Appears on: +OpenStackMachineSpec, +PortOpts) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
++ | +
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +SecurityGroup) +
++
SecurityGroupRule represent the basic information of the associated OpenStack +Security Group Role.
+ +| Field | +Description | +
|---|---|
+description+ +string + + |
++ | +
+name+ +string + + |
++ | +
+direction+ +string + + |
++ | +
+etherType+ +string + + |
++ | +
+securityGroupID+ +string + + |
++ | +
+portRangeMin+ +int + + |
++ | +
+portRangeMax+ +int + + |
++ | +
+protocol+ +string + + |
++ | +
+remoteGroupID+ +string + + |
++ | +
+remoteIPPrefix+ +string + + |
++ | +
+(Appears on: +NetworkStatusWithSubnets) +
++
Subnet represents basic information about the associated OpenStack Neutron Subnet.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+cidr+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +ExternalRouterIPParam, +FixedIP, +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectId+ +string + + |
++ | +
+ipVersion+ +int + + |
++ | +
+gateway_ip+ +string + + |
++ | +
+cidr+ +string + + |
++ | +
+ipv6AddressMode+ +string + + |
++ | +
+ipv6RaMode+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +string + + |
++ | +
+tagsAny+ +string + + |
++ | +
+notTags+ +string + + |
++ | +
+notTagsAny+ +string + + |
++ | +
+(Appears on: +PortOpts) +
++
ValueSpec represents a single value_spec key-value pair.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name is the name of the key-value pair. +This is just for identifying the pair and will not be sent to the OpenStack API. + |
+
+key+ +string + + |
+
+ Key is the key in the key-value pair. + |
+
+value+ +string + + |
+
+ Value is the value in the key-value pair. + |
+
+Generated with gen-crd-api-reference-docs.
+
+
Package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group.
+ +Resource Types: + ++
OpenStackCluster is the Schema for the openstackclusters API.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1beta1
+
+ |
+||||||||||||||||||||||||||||||||||||||||||
+kind+string + |
+OpenStackCluster |
+||||||||||||||||||||||||||||||||||||||||||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||||||||||||||||||||||||||||||||
+spec+ + +OpenStackClusterSpec + + + |
+
+ + +
|
+||||||||||||||||||||||||||||||||||||||||||
+status+ + +OpenStackClusterStatus + + + |
++ | +
+
OpenStackClusterTemplate is the Schema for the openstackclustertemplates API.
+ +| Field | +Description | +||
|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1beta1
+
+ |
+||
+kind+string + |
+OpenStackClusterTemplate |
+||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||
+spec+ + +OpenStackClusterTemplateSpec + + + |
+
+ + +
|
+
+
OpenStackMachine is the Schema for the openstackmachines API.
+ +| Field | +Description | +||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1beta1
+
+ |
+||||||||||||||||||||||||||||||
+kind+string + |
+OpenStackMachine |
+||||||||||||||||||||||||||||||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||||||||||||||||||||
+spec+ + +OpenStackMachineSpec + + + |
+
+ + +
|
+||||||||||||||||||||||||||||||
+status+ + +OpenStackMachineStatus + + + |
++ | +
+
OpenStackMachineTemplate is the Schema for the openstackmachinetemplates API.
+ +| Field | +Description | +||
|---|---|---|---|
+apiVersion+string |
+
+
+infrastructure.cluster.x-k8s.io/v1beta1
+
+ |
+||
+kind+string + |
+OpenStackMachineTemplate |
+||
+metadata+ +Kubernetes meta/v1.ObjectMeta + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||
+spec+ + +OpenStackMachineTemplateSpec + + + |
+
+ + +
|
+
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+enabled+ +bool + + |
+
+ Enabled defines whether a load balancer should be created. This value +defaults to true if an APIServerLoadBalancer is given. +There is no reason to set this to false. To disable creation of the +API server loadbalancer, omit the APIServerLoadBalancer field in the +cluster spec instead. + |
+
+additionalPorts+ +[]int + + |
+
+(Optional)
+ AdditionalPorts adds additional tcp ports to the load balancer. + |
+
+allowedCIDRs+ +[]string + + |
+
+(Optional)
+ AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs. + |
+
+provider+ +string + + |
+
+(Optional)
+ Provider specifies name of a specific Octavia provider to use for the +API load balancer. The Octavia default will be used if it is not +specified. + |
+
+network+ + +NetworkParam + + + |
+
+(Optional)
+ Network defines which network should the load balancer be allocated on. + |
+
+subnets+ + +[]SubnetParam + + + |
+
+(Optional)
+ Subnets define which subnets should the load balancer be allocated on. +It is expected that subnets are located on the network specified in this resource. +Only the first element is taken into account. +kubebuilder:validation:MaxLength:=2 + |
+
+availabilityZone+ +string + + |
+
+(Optional)
+ AvailabilityZone is the failure domain that will be used to create the APIServerLoadBalancer Spec. + |
+
+(Appears on: +OpenStackMachineSpec) +
++
AdditionalBlockDevice is a block device to attach to the server.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name of the block device in the context of a machine. +If the block device is a volume, the Cinder volume will be named +as a combination of the machine name and this name. +Also, this name will be used for tagging the block device. +Information about the block device tag can be obtained from the OpenStack +metadata API or the config drive. +Name cannot be ‘root’, which is reserved for the root volume. + |
+
+sizeGiB+ +int + + |
+
+ SizeGiB is the size of the block device in gibibytes (GiB). + |
+
+storage+ + +BlockDeviceStorage + + + |
+
+ Storage specifies the storage type of the block device and +additional storage options. + |
+
+(Appears on: +ResolvedPortSpecFields) +
++
+| Field | +Description | +
|---|---|
+ipAddress+ +string + + |
+
+ IPAddress is the IP address of the allowed address pair. Depending on +the configuration of Neutron, it may be supported to specify a CIDR +instead of a specific IP address. + |
+
+macAddress+ +string + + |
+
+(Optional)
+ MACAddress is the MAC address of the allowed address pair. If not +specified, the MAC address will be the MAC address of the port. + |
+
+(Appears on: +SubnetSpec) +
++
+| Field | +Description | +
|---|---|
+start+ +string + + |
+
+ Start represents the start of the AllocationPool, that is the lowest IP of the pool. + |
+
+end+ +string + + |
+
+ End represents the end of the AlloctionPool, that is the highest IP of the pool. + |
+
+(Appears on: +OpenStackClusterSpec) +
++
Bastion represents basic information about the bastion node. If you enable bastion, the spec has to be specified.
+ +| Field | +Description | +
|---|---|
+enabled+ +bool + + |
+
+(Optional)
+ Enabled means that bastion is enabled. The bastion is enabled by +default if this field is not specified. Set this field to false to disable the +bastion. +It is not currently possible to remove the bastion from the cluster +spec without first disabling it by setting this field to false and +waiting until the bastion has been deleted. + |
+
+spec+ + +OpenStackMachineSpec + + + |
+
+ Spec for the bastion itself ++ + |
+
+availabilityZone+ +string + + |
+
+(Optional)
+ AvailabilityZone is the failure domain that will be used to create the Bastion Spec. + |
+
+floatingIP+ +string + + |
+
+(Optional)
+ FloatingIP which will be associated to the bastion machine. It’s the IP address, not UUID. +The floating IP should already exist and should not be associated with a port. If FIP of this address does not +exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so. + |
+
+(Appears on: +OpenStackClusterStatus) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
++ | +
+name+ +string + + |
++ | +
+sshKeyName+ +string + + |
++ | +
+state+ + +InstanceState + + + |
++ | +
+ip+ +string + + |
++ | +
+floatingIP+ +string + + |
++ | +
+resolved+ + +ResolvedMachineSpec + + + |
+
+(Optional)
+ Resolved contains parts of the bastion’s machine spec with all +external references fully resolved. + |
+
+resources+ + +MachineResources + + + |
+
+(Optional)
+ Resources contains references to OpenStack resources created for the bastion. + |
+
+(Appears on: +ResolvedPortSpecFields) +
++
+| Field | +Description | +
|---|---|
+ovsHWOffload+ +bool + + |
+
+(Optional)
+ OVSHWOffload enables or disables the OVS hardware offload feature. + |
+
+trustedVF+ +bool + + |
+
+(Optional)
+ TrustedVF enables or disables the “trusted mode” for the VF. + |
+
+(Appears on: +AdditionalBlockDevice) +
++
BlockDeviceStorage is the storage type of a block device to create and +contains additional storage options.
+ +| Field | +Description | +
|---|---|
+type+ + +BlockDeviceType + + + |
+
+ Type is the type of block device to create. +This can be either “Volume” or “Local”. + |
+
+volume+ + +BlockDeviceVolume + + + |
+
+(Optional)
+ Volume contains additional storage options for a volume block device. + |
+
string alias)+(Appears on: +BlockDeviceStorage) +
++
BlockDeviceType defines the type of block device to create.
+ +| Value | +Description | +
|---|---|
"Local" |
+LocalBlockDevice is an ephemeral block device attached to the server. + |
+
"Volume" |
+VolumeBlockDevice is a volume block device attached to the server. + |
+
+(Appears on: +BlockDeviceStorage, +RootVolume) +
++
BlockDeviceVolume contains additional storage options for a volume block device.
+ +| Field | +Description | +
|---|---|
+type+ +string + + |
+
+(Optional)
+ Type is the Cinder volume type of the volume. +If omitted, the default Cinder volume type that is configured in the OpenStack cloud +will be used. + |
+
+availabilityZone+ + +VolumeAvailabilityZone + + + |
+
+(Optional)
+ AvailabilityZone is the volume availability zone to create the volume +in. If not specified, the volume will be created without an explicit +availability zone. + |
+
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+fixedIP+ +string + + |
+
+ The FixedIP in the corresponding subnet + |
+
+subnet+ + +SubnetParam + + + |
+
+ The subnet in which the FixedIP is used for the Gateway of this router + |
+
+(Appears on: +NetworkFilter, +RouterFilter, +SecurityGroupFilter, +SubnetFilter) +
++
+| Field | +Description | +
|---|---|
+tags+ + +[]NeutronTag + + + |
+
+(Optional)
+ Tags is a list of tags to filter by. If specified, the resource must +have all of the tags specified to be included in the result. + |
+
+tagsAny+ + +[]NeutronTag + + + |
+
+(Optional)
+ TagsAny is a list of tags to filter by. If specified, the resource +must have at least one of the tags specified to be included in the +result. + |
+
+notTags+ + +[]NeutronTag + + + |
+
+(Optional)
+ NotTags is a list of tags to filter by. If specified, resources which +contain all of the given tags will be excluded from the result. + |
+
+notTagsAny+ + +[]NeutronTag + + + |
+
+(Optional)
+ NotTagsAny is a list of tags to filter by. If specified, resources +which contain any of the given tags will be excluded from the result. + |
+
+(Appears on: +PortOpts) +
++
+| Field | +Description | +
|---|---|
+subnet+ + +SubnetParam + + + |
+
+(Optional)
+ Subnet is an openstack subnet query that will return the id of a subnet to create +the fixed IP of a port in. This query must not return more than one subnet. + |
+
+ipAddress+ +string + + |
+
+(Optional)
+ IPAddress is a specific IP address to assign to the port. If Subnet +is also specified, IPAddress must be a valid IP address in the +subnet. If Subnet is not specified, IPAddress must be a valid IP +address in any subnet of the port’s network. + |
+
+(Appears on: +ImageParam) +
++
ImageFilter describes a query for an image.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+(Optional)
+ The name of the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised. + |
+
+tags+ +[]string + + |
+
+(Optional)
+ The tags associated with the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised. + |
+
+(Appears on: +OpenStackMachineSpec) +
++
ImageParam describes a glance image. It can be specified by ID or filter.
+ +| Field | +Description | +
|---|---|
+id+ +string + + |
+
+(Optional)
+ ID is the uuid of the image. ID will not be validated before use. + |
+
+filter+ + +ImageFilter + + + |
+
+(Optional)
+ Filter describes a query for an image. If specified, the combination +of name and tags must return a single matching image or an error will +be raised. + |
+
string alias)+(Appears on: +BastionStatus, +OpenStackMachineStatus) +
++
InstanceState describes the state of an OpenStack instance.
+ ++(Appears on: +OpenStackClusterStatus) +
++
LoadBalancer represents basic information about the associated OpenStack LoadBalancer.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+ip+ +string + + |
++ | +
+internalIP+ +string + + |
++ | +
+allowedCIDRs+ +[]string + + |
++(Optional) + | +
+tags+ +[]string + + |
++(Optional) + | +
+loadBalancerNetwork+ + +NetworkStatusWithSubnets + + + |
+
+(Optional)
+ LoadBalancerNetwork contains information about network and/or subnets which the +loadbalancer is allocated on. +If subnets are specified within the LoadBalancerNetwork currently only the first +subnet in the list is taken into account. + |
+
+(Appears on: +BastionStatus, +OpenStackMachineStatus) +
++
+| Field | +Description | +
|---|---|
+ports+ + +[]PortStatus + + + |
+
+(Optional)
+ Ports is the status of the ports created for the machine. + |
+
string alias)+(Appears on: +SecurityGroupRuleSpec) +
++
++(Appears on: +OpenStackClusterSpec) +
++
ManagedSecurityGroups defines the desired state of security groups and rules for the cluster.
+ +| Field | +Description | +
|---|---|
+allNodesSecurityGroupRules+ + +[]SecurityGroupRuleSpec + + + |
+
+(Optional)
+ allNodesSecurityGroupRules defines the rules that should be applied to all nodes. + |
+
+allowAllInClusterTraffic+ +bool + + |
+
+ AllowAllInClusterTraffic allows all ingress and egress traffic between cluster nodes when set to true. + |
+
+(Appears on: +NetworkParam) +
++
NetworkFilter specifies a query to select an OpenStack network. At least one property must be set.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectID+ +string + + |
++ | +
+FilterByNeutronTags+ + +FilterByNeutronTags + + + |
+
+
+(Members of |
+
+(Appears on: +APIServerLoadBalancer, +OpenStackClusterSpec, +PortOpts) +
++
NetworkParam specifies an OpenStack network. It may be specified by either ID or Filter, but not both.
+ +| Field | +Description | +
|---|---|
+id+ +string + + |
+
+(Optional)
+ ID is the ID of the network to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + |
+
+filter+ + +NetworkFilter + + + |
+
+(Optional)
+ Filter specifies a filter to select an OpenStack network. If provided, cannot be empty. + |
+
+(Appears on: +NetworkStatusWithSubnets, +OpenStackClusterStatus) +
++
NetworkStatus contains basic information about an existing neutron network.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +LoadBalancer, +OpenStackClusterStatus) +
++
NetworkStatusWithSubnets represents basic information about an existing neutron network and an associated set of subnets.
+ +| Field | +Description | +
|---|---|
+NetworkStatus+ + +NetworkStatus + + + |
+
+
+(Members of |
+
+subnets+ + +[]Subnet + + + |
+
+ Subnets is a list of subnets associated with the default cluster network. Machines which use the default cluster network will get an address from all of these subnets. + |
+
string alias)+(Appears on: +FilterByNeutronTags) +
++
NeutronTag represents a tag on a Neutron resource. +It may not be empty and may not contain commas.
+ ++(Appears on: +OpenStackCluster, +OpenStackClusterTemplateResource) +
++
OpenStackClusterSpec defines the desired state of OpenStackCluster.
+ +| Field | +Description | +
|---|---|
+managedSubnets+ + +[]SubnetSpec + + + |
+
+(Optional)
+ ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network, +subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4 +subnet is supported. If you leave this empty, no network will be created. + |
+
+router+ + +RouterParam + + + |
+
+(Optional)
+ Router specifies an existing router to be used if ManagedSubnets are +specified. If specified, no new router will be created. + |
+
+network+ + +NetworkParam + + + |
+
+(Optional)
+ Network specifies an existing network to use if no ManagedSubnets +are specified. + |
+
+subnets+ + +[]SubnetParam + + + |
+
+(Optional)
+ Subnets specifies existing subnets to use if not ManagedSubnets are +specified. All subnets must be in the network specified by Network. +There can be zero, one, or two subnets. If no subnets are specified, +all subnets in Network will be used. If 2 subnets are specified, one +must be IPv4 and the other IPv6. + |
+
+networkMTU+ +int + + |
+
+(Optional)
+ NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. +This value will be used only if the Cluster actuator creates the network. +If left empty, the network will have the default MTU defined in Openstack network service. +To use this field, the Openstack installation requires the net-mtu neutron API extension. + |
+
+externalRouterIPs+ + +[]ExternalRouterIPParam + + + |
+
+(Optional)
+ ExternalRouterIPs is an array of externalIPs on the respective subnets. +This is necessary if the router needs a fixed ip in a specific subnet. + |
+
+externalNetwork+ + +NetworkParam + + + |
+
+(Optional)
+ ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. +This option is ignored if DisableExternalNetwork is set to true. +If ExternalNetwork is defined it must refer to exactly one external network. +If ExternalNetwork is not defined or is empty the controller will use any +existing external network as long as there is only one. It is an +error if ExternalNetwork is not defined and there are multiple +external networks unless DisableExternalNetwork is also set. +If ExternalNetwork is not defined and there are no external networks +the controller will proceed as though DisableExternalNetwork was set. + |
+
+disableExternalNetwork+ +bool + + |
+
+(Optional)
+ DisableExternalNetwork specifies whether or not to attempt to connect the cluster +to an external network. This allows for the creation of clusters when connecting +to an external network is not possible or desirable, e.g. if using a provider network. + |
+
+apiServerLoadBalancer+ + +APIServerLoadBalancer + + + |
+
+(Optional)
+ APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. +If not specified, no load balancer will be created for the API server. + |
+
+disableAPIServerFloatingIP+ +bool + + |
+
+(Optional)
+ DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating +IP to the API server. This allows for the creation of clusters when attaching a floating +IP to the API server (and hence, in many cases, exposing the API server to the internet) +is not possible or desirable, e.g. if using a shared VLAN for communication between +management and workload clusters or when the management cluster is inside the +project network. +This option requires that the API server use a VIP on the cluster network so that the +underlying machines can change without changing ControlPlaneEndpoint.Host. +When using a managed load balancer, this VIP will be managed automatically. +If not using a managed load balancer, cluster configuration will fail without additional +configuration to manage the VIP on the control plane machines, which falls outside of +the scope of this controller. + |
+
+apiServerFloatingIP+ +string + + |
+
+(Optional)
+ APIServerFloatingIP is the floatingIP which will be associated with the API server. +The floatingIP will be created if it does not already exist. +If not specified, a new floatingIP is allocated. +This field is not used if DisableAPIServerFloatingIP is set to true. + |
+
+apiServerFixedIP+ +string + + |
+
+(Optional)
+ APIServerFixedIP is the fixed IP which will be associated with the API server. +In the case where the API server has a floating IP but not a managed load balancer, +this field is not used. +If a managed load balancer is used and this field is not specified, a fixed IP will +be dynamically allocated for the load balancer. +If a managed load balancer is not used AND the API server floating IP is disabled, +this field MUST be specified and should correspond to a pre-allocated port that +holds the fixed IP to be used as a VIP. + |
+
+apiServerPort+ +int + + |
+
+(Optional)
+ APIServerPort is the port on which the listener on the APIServer +will be created + |
+
+managedSecurityGroups+ + +ManagedSecurityGroups + + + |
+
+(Optional)
+ ManagedSecurityGroups determines whether OpenStack security groups for the cluster +will be managed by the OpenStack provider or whether pre-existing security groups will +be specified as part of the configuration. +By default, the managed security groups have rules that allow the Kubelet, etcd, and the +Kubernetes API server to function correctly. +It’s possible to add additional rules to the managed security groups. +When defined to an empty struct, the managed security groups will be created with the default rules. + |
+
+disablePortSecurity+ +bool + + |
+
+(Optional)
+ DisablePortSecurity disables the port security of the network created for the +Kubernetes cluster, which also disables SecurityGroups + |
+
+tags+ +[]string + + |
+
+(Optional)
+ Tags to set on all resources in cluster which support tags + |
+
+controlPlaneEndpoint+ + +sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint + + + |
+
+(Optional)
+ ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. +It is normally populated automatically by the OpenStackCluster +controller during cluster provisioning. If it is set on creation the +control plane endpoint will use the values set here in preference to +values set elsewhere. +ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set. + |
+
+controlPlaneAvailabilityZones+ +[]string + + |
+
+(Optional)
+ ControlPlaneAvailabilityZones is the set of availability zones which +control plane machines may be deployed to. + |
+
+controlPlaneOmitAvailabilityZone+ +bool + + |
+
+(Optional)
+ ControlPlaneOmitAvailabilityZone causes availability zone to be +omitted when creating control plane nodes, allowing the Nova +scheduler to make a decision on which availability zone to use based +on other scheduling constraints + |
+
+bastion+ + +Bastion + + + |
+
+(Optional)
+ Bastion is the OpenStack instance to login the nodes +As a rolling update is not ideal during a bastion host session, we
+prevent changes to a running bastion configuration. To make changes, it’s required
+to first set |
+
+identityRef+ + +OpenStackIdentityReference + + + |
+
+ IdentityRef is a reference to a secret holding OpenStack credentials +to be used when reconciling this cluster. It is also to reconcile +machines unless overridden in the machine spec. + |
+
+(Appears on: +OpenStackCluster) +
++
OpenStackClusterStatus defines the observed state of OpenStackCluster.
+ +| Field | +Description | +
|---|---|
+ready+ +bool + + |
+
+ Ready is true when the cluster infrastructure is ready. + |
+
+network+ + +NetworkStatusWithSubnets + + + |
+
+(Optional)
+ Network contains information about the created OpenStack Network. + |
+
+externalNetwork+ + +NetworkStatus + + + |
+
+(Optional)
+ ExternalNetwork contains information about the external network used for default ingress and egress traffic. + |
+
+router+ + +Router + + + |
+
+(Optional)
+ Router describes the default cluster router + |
+
+apiServerLoadBalancer+ + +LoadBalancer + + + |
+
+(Optional)
+ APIServerLoadBalancer describes the api server load balancer if one exists + |
+
+failureDomains+ + +sigs.k8s.io/cluster-api/api/v1beta1.FailureDomains + + + |
+
+ FailureDomains represent OpenStack availability zones + |
+
+controlPlaneSecurityGroup+ + +SecurityGroupStatus + + + |
+
+(Optional)
+ ControlPlaneSecurityGroup contains the information about the +OpenStack Security Group that needs to be applied to control plane +nodes. + |
+
+workerSecurityGroup+ + +SecurityGroupStatus + + + |
+
+(Optional)
+ WorkerSecurityGroup contains the information about the OpenStack +Security Group that needs to be applied to worker nodes. + |
+
+bastionSecurityGroup+ + +SecurityGroupStatus + + + |
+
+(Optional)
+ BastionSecurityGroup contains the information about the OpenStack +Security Group that needs to be applied to worker nodes. + |
+
+bastion+ + +BastionStatus + + + |
+
+(Optional)
+ Bastion contains the information about the deployed bastion host + |
+
+failureReason+ + +sigs.k8s.io/cluster-api/errors.ClusterStatusError + + + |
+
+(Optional)
+ FailureReason will be set in the event that there is a terminal problem +reconciling the OpenStackCluster and will contain a succinct value suitable +for machine interpretation. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the OpenStackCluster’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of +OpenStackClusters can be added as events to the OpenStackCluster object +and/or logged in the controller’s output. + |
+
+failureMessage+ +string + + |
+
+(Optional)
+ FailureMessage will be set in the event that there is a terminal problem +reconciling the OpenStackCluster and will contain a more verbose string suitable +for logging and human consumption. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the OpenStackCluster’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of +OpenStackClusters can be added as events to the OpenStackCluster object +and/or logged in the controller’s output. + |
+
+(Appears on: +OpenStackClusterTemplateSpec) +
++
OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+ +| Field | +Description | +||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+spec+ + +OpenStackClusterSpec + + + |
+
+ + +
|
+
+(Appears on: +OpenStackClusterTemplate) +
++
OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+ +| Field | +Description | +
|---|---|
+template+ + +OpenStackClusterTemplateResource + + + |
++ | +
+(Appears on: +OpenStackClusterSpec, +OpenStackMachineSpec) +
++
OpenStackIdentityReference is a reference to an infrastructure +provider identity to be used to provision cluster resources.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name is the name of a secret in the same namespace as the resource being provisioned.
+The secret must contain a key named |
+
+cloudName+ +string + + |
+
+ CloudName specifies the name of the entry in the clouds.yaml file to use. + |
+
+(Appears on: +OpenStackMachine, +Bastion, +OpenStackMachineTemplateResource) +
++
OpenStackMachineSpec defines the desired state of OpenStackMachine.
+ +| Field | +Description | +
|---|---|
+providerID+ +string + + |
+
+ ProviderID is the unique identifier as specified by the cloud provider. + |
+
+flavor+ +string + + |
+
+ The flavor reference for the flavor for your server instance. + |
+
+image+ + +ImageParam + + + |
+
+ The image to use for your server instance. +If the rootVolume is specified, this will be used when creating the root volume. + |
+
+sshKeyName+ +string + + |
+
+ The ssh key to inject in the instance + |
+
+ports+ + +[]PortOpts + + + |
+
+ Ports to be attached to the server instance. They are created if a port with the given name does not already exist. +If not specified a default port will be added for the default cluster network. + |
+
+securityGroups+ + +[]SecurityGroupParam + + + |
+
+ The names of the security groups to assign to the instance + |
+
+trunk+ +bool + + |
+
+ Whether the server instance is created on a trunk port or not. + |
+
+tags+ +[]string + + |
+
+ Tags which will be added to the machine and all dependent resources +which support them. These are in addition to Tags defined on the +cluster. +Requires Nova api 2.52 minimum! + |
+
+serverMetadata+ + +[]ServerMetadata + + + |
+
+ Metadata mapping. Allows you to create a map of key value pairs to add to the server instance. + |
+
+configDrive+ +bool + + |
+
+ Config Drive support + |
+
+rootVolume+ + +RootVolume + + + |
+
+ The volume metadata to boot from + |
+
+additionalBlockDevices+ + +[]AdditionalBlockDevice + + + |
+
+(Optional)
+ AdditionalBlockDevices is a list of specifications for additional block devices to attach to the server instance + |
+
+serverGroup+ + +ServerGroupParam + + + |
+
+(Optional)
+ The server group to assign the machine to. + |
+
+identityRef+ + +OpenStackIdentityReference + + + |
+
+(Optional)
+ IdentityRef is a reference to a secret holding OpenStack credentials +to be used when reconciling this machine. If not specified, the +credentials specified in the cluster will be used. + |
+
+floatingIPPoolRef+ +Kubernetes core/v1.TypedLocalObjectReference + + |
+
+(Optional)
+ floatingIPPoolRef is a reference to a IPPool that will be assigned +to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP +will be assigned to the OpenStackMachine. + |
+
+(Appears on: +OpenStackMachine) +
++
OpenStackMachineStatus defines the observed state of OpenStackMachine.
+ +| Field | +Description | +
|---|---|
+ready+ +bool + + |
+
+(Optional)
+ Ready is true when the provider resource is ready. + |
+
+instanceID+ +string + + |
+
+(Optional)
+ InstanceID is the OpenStack instance ID for this machine. + |
+
+addresses+ +[]Kubernetes core/v1.NodeAddress + + |
+
+ Addresses contains the OpenStack instance associated addresses. + |
+
+instanceState+ + +InstanceState + + + |
+
+(Optional)
+ InstanceState is the state of the OpenStack instance for this machine. + |
+
+resolved+ + +ResolvedMachineSpec + + + |
+
+(Optional)
+ Resolved contains parts of the machine spec with all external +references fully resolved. + |
+
+resources+ + +MachineResources + + + |
+
+(Optional)
+ Resources contains references to OpenStack resources created for the machine. + |
+
+failureReason+ + +sigs.k8s.io/cluster-api/errors.MachineStatusError + + + |
++ | +
+failureMessage+ +string + + |
+
+(Optional)
+ FailureMessage will be set in the event that there is a terminal problem +reconciling the Machine and will contain a more verbose string suitable +for logging and human consumption. +This field should not be set for transitive errors that a controller +faces that are expected to be fixed automatically over +time (like service outages), but instead indicate that something is +fundamentally wrong with the Machine’s spec or the configuration of +the controller, and that manual intervention is required. Examples +of terminal errors would be invalid combinations of settings in the +spec, values that are unsupported by the controller, or the +responsible controller itself being critically misconfigured. +Any transient errors that occur during the reconciliation of Machines +can be added as events to the Machine object and/or logged in the +controller’s output. + |
+
+conditions+ + +sigs.k8s.io/cluster-api/api/v1beta1.Conditions + + + |
++ | +
+(Appears on: +OpenStackMachineTemplateSpec) +
++
OpenStackMachineTemplateResource describes the data needed to create a OpenStackMachine from a template.
+ +| Field | +Description | +||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+spec+ + +OpenStackMachineSpec + + + |
+
+ Spec is the specification of the desired behavior of the machine. ++ +
|
+
+(Appears on: +OpenStackMachineTemplate) +
++
OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+ +| Field | +Description | +
|---|---|
+template+ + +OpenStackMachineTemplateResource + + + |
++ | +
+(Appears on: +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+network+ + +NetworkParam + + + |
+
+(Optional)
+ Network is a query for an openstack network that the port will be created or discovered on. +This will fail if the query returns more than one network. + |
+
+description+ +string + + |
+
+(Optional)
+ Description is a human-readable description for the port. + |
+
+nameSuffix+ +string + + |
+
+(Optional)
+ NameSuffix will be appended to the name of the port if specified. If unspecified, instead the 0-based index of the port in the list is used. + |
+
+fixedIPs+ + +[]FixedIP + + + |
+
+(Optional)
+ FixedIPs is a list of pairs of subnet and/or IP address to assign to the port. If specified, these must be subnets of the port’s network. + |
+
+securityGroups+ + +[]SecurityGroupParam + + + |
+
+(Optional)
+ SecurityGroups is a list of the names, uuids, filters or any combination these of the security groups to assign to the instance. + |
+
+tags+ +[]string + + |
+
+(Optional)
+ Tags applied to the port (and corresponding trunk, if a trunk is configured.) +These tags are applied in addition to the instance’s tags, which will also be applied to the port. + |
+
+trunk+ +bool + + |
+
+(Optional)
+ Trunk specifies whether trunking is enabled at the port level. If not +provided the value is inherited from the machine, or false for a +bastion host. + |
+
+ResolvedPortSpecFields+ + +ResolvedPortSpecFields + + + |
+
+
+(Members of |
+
+(Appears on: +MachineResources) +
++
+| Field | +Description | +
|---|---|
+id+ +string + + |
+
+ ID is the unique identifier of the port. + |
+
+(Appears on: +ResolvedPortSpec) +
++
ResolvedFixedIP is a FixedIP with the Subnet resolved to an ID.
+ +| Field | +Description | +
|---|---|
+subnet+ +string + + |
+
+(Optional)
+ SubnetID is the id of a subnet to create the fixed IP of a port in. + |
+
+ipAddress+ +string + + |
+
+(Optional)
+ IPAddress is a specific IP address to assign to the port. If SubnetID +is also specified, IPAddress must be a valid IP address in the +subnet. If Subnet is not specified, IPAddress must be a valid IP +address in any subnet of the port’s network. + |
+
+(Appears on: +BastionStatus, +OpenStackMachineStatus) +
++
ResolvedMachineSpec contains resolved references to resources required by the machine.
+ +| Field | +Description | +
|---|---|
+serverGroupID+ +string + + |
+
+(Optional)
+ ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter. + |
+
+imageID+ +string + + |
+
+(Optional)
+ ImageID is the ID of the image to use for the machine and is calculated based on ImageFilter. + |
+
+ports+ + +[]ResolvedPortSpec + + + |
+
+(Optional)
+ Ports is the fully resolved list of ports to create for the machine. + |
+
+(Appears on: +ResolvedMachineSpec) +
++
ResolvedPortSpec is a PortOpts with all contained references fully resolved.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name is the name of the port. + |
+
+description+ +string + + |
+
+ Description is a human-readable description for the port. + |
+
+networkID+ +string + + |
+
+ NetworkID is the ID of the network the port will be created in. + |
+
+tags+ +[]string + + |
+
+(Optional)
+ Tags applied to the port (and corresponding trunk, if a trunk is configured.) + |
+
+trunk+ +bool + + |
+
+(Optional)
+ Trunk specifies whether trunking is enabled at the port level. + |
+
+fixedIPs+ + +[]ResolvedFixedIP + + + |
+
+(Optional)
+ FixedIPs is a list of pairs of subnet and/or IP address to assign to the port. If specified, these must be subnets of the port’s network. + |
+
+securityGroups+ +[]string + + |
+
+(Optional)
+ SecurityGroups is a list of security group IDs to assign to the port. + |
+
+ResolvedPortSpecFields+ + +ResolvedPortSpecFields + + + |
+
+
+(Members of |
+
+(Appears on: +PortOpts, +ResolvedPortSpec) +
++
ResolvePortSpecFields is a convenience struct containing all fields of a +PortOpts which don’t contain references which need to be resolved, and can +therefore be shared with ResolvedPortSpec.
+ +| Field | +Description | +
|---|---|
+adminStateUp+ +bool + + |
+
+(Optional)
+ AdminStateUp specifies whether the port should be created in the up (true) or down (false) state. The default is up. + |
+
+macAddress+ +string + + |
+
+(Optional)
+ MACAddress specifies the MAC address of the port. If not specified, the MAC address will be generated. + |
+
+allowedAddressPairs+ + +[]AddressPair + + + |
+
+(Optional)
+ AllowedAddressPairs is a list of address pairs which Neutron will +allow the port to send traffic from in addition to the port’s +addresses. If not specified, the MAC Address will be the MAC Address +of the port. Depending on the configuration of Neutron, it may be +supported to specify a CIDR instead of a specific IP address. + |
+
+hostID+ +string + + |
+
+(Optional)
+ HostID specifies the ID of the host where the port resides. + |
+
+vnicType+ +string + + |
+
+(Optional)
+ VNICType specifies the type of vNIC which this port should be +attached to. This is used to determine which mechanism driver(s) to +be used to bind the port. The valid values are normal, macvtap, +direct, baremetal, direct-physical, virtio-forwarder, smart-nic and +remote-managed, although these values will not be validated in this +API to ensure compatibility with future neutron changes or custom +implementations. What type of vNIC is actually available depends on +deployments. If not specified, the Neutron default value is used. + |
+
+profile+ + +BindingProfile + + + |
+
+(Optional)
+ Profile is a set of key-value pairs that are used for binding +details. We intentionally don’t expose this as a map[string]string +because we only want to enable the users to set the values of the +keys that are known to work in OpenStack Networking API. See +https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port +To set profiles, your tenant needs permissions rule:create_port, and +rule:create_port:binding:profile + |
+
+disablePortSecurity+ +bool + + |
+
+(Optional)
+ DisablePortSecurity enables or disables the port security when set. +When not set, it takes the value of the corresponding field at the network level. + |
+
+propagateUplinkStatus+ +bool + + |
+
+(Optional)
+ PropageteUplinkStatus enables or disables the propagate uplink status on the port. + |
+
+valueSpecs+ + +[]ValueSpec + + + |
+
+(Optional)
+ Value specs are extra parameters to include in the API request with OpenStack. +This is an extension point for the API, so what they do and if they are supported, +depends on the specific OpenStack implementation. + |
+
+(Appears on: +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+sizeGiB+ +int + + |
+
+ SizeGiB is the size of the block device in gibibytes (GiB). + |
+
+BlockDeviceVolume+ + +BlockDeviceVolume + + + |
+
+
+(Members of |
+
+(Appears on: +OpenStackClusterStatus) +
++
Router represents basic information about the associated OpenStack Neutron Router.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+ips+ +[]string + + |
++(Optional) + | +
+(Appears on: +RouterParam) +
++
RouterFilter specifies a query to select an OpenStack router. At least one property must be set.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectID+ +string + + |
++ | +
+FilterByNeutronTags+ + +FilterByNeutronTags + + + |
+
+
+(Members of |
+
+(Appears on: +OpenStackClusterSpec) +
++
RouterParam specifies an OpenStack router to use. It may be specified by either ID or filter, but not both.
+ +| Field | +Description | +
|---|---|
+id+ +string + + |
+
+(Optional)
+ ID is the ID of the router to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + |
+
+filter+ + +RouterFilter + + + |
+
+ Filter specifies a filter to select an OpenStack router. If provided, cannot be empty. + |
+
+(Appears on: +SecurityGroupParam) +
++
SecurityGroupFilter specifies a query to select an OpenStack security group. At least one property must be set.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectID+ +string + + |
++ | +
+FilterByNeutronTags+ + +FilterByNeutronTags + + + |
+
+
+(Members of |
+
+(Appears on: +OpenStackMachineSpec, +PortOpts) +
++
SecurityGroupParam specifies an OpenStack security group. It may be specified by ID or filter, but not both.
+ +| Field | +Description | +
|---|---|
+id+ +string + + |
+
+(Optional)
+ ID is the ID of the security group to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + |
+
+filter+ + +SecurityGroupFilter + + + |
+
+(Optional)
+ Filter specifies a query to select an OpenStack security group. If provided, cannot be empty. + |
+
+(Appears on: +ManagedSecurityGroups) +
++
SecurityGroupRuleSpec represent the basic information of the associated OpenStack +Security Group Role. +For now this is only used for the allNodesSecurityGroupRules but when we add +other security groups, we’ll need to add a validation because +Remote* fields are mutually exclusive.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ name of the security group rule. +It’s used to identify the rule so it can be patched and will not be sent to the OpenStack API. + |
+
+description+ +string + + |
+
+(Optional)
+ description of the security group rule. + |
+
+direction+ +string + + |
+
+ direction in which the security group rule is applied. The only values +allowed are “ingress” or “egress”. For a compute instance, an ingress +security group rule is applied to incoming (ingress) traffic for that +instance. An egress rule is applied to traffic leaving the instance. + |
+
+etherType+ +string + + |
+
+(Optional)
+ etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the +ingress or egress rules. + |
+
+portRangeMin+ +int + + |
+
+(Optional)
+ portRangeMin is a number in the range that is matched by the security group +rule. If the protocol is TCP or UDP, this value must be less than or equal +to the value of the portRangeMax attribute. + |
+
+portRangeMax+ +int + + |
+
+(Optional)
+ portRangeMax is a number in the range that is matched by the security group +rule. The portRangeMin attribute constrains the portRangeMax attribute. + |
+
+protocol+ +string + + |
+
+(Optional)
+ protocol is the protocol that is matched by the security group rule. + |
+
+remoteGroupID+ +string + + |
+
+(Optional)
+ remoteGroupID is the remote group ID to be associated with this security group rule. +You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + |
+
+remoteIPPrefix+ +string + + |
+
+(Optional)
+ remoteIPPrefix is the remote IP prefix to be associated with this security group rule. +You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + |
+
+remoteManagedGroups+ + +[]ManagedSecurityGroupName + + + |
+
+(Optional)
+ remoteManagedGroups is the remote managed groups to be associated with this security group rule. +You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. + |
+
+(Appears on: +OpenStackClusterStatus) +
++
SecurityGroupStatus represents the basic information of the associated +OpenStack Neutron Security Group.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ name of the security group + |
+
+id+ +string + + |
+
+ id of the security group + |
+
+(Appears on: +ServerGroupParam) +
++
ServerGroupFilter specifies a query to select an OpenStack server group. At least one property must be set.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name is the name of a server group to look for. + |
+
+(Appears on: +OpenStackMachineSpec) +
++
ServerGroupParam specifies an OpenStack server group. It may be specified by ID or filter, but not both.
+ +| Field | +Description | +
|---|---|
+id+ +string + + |
+
+ ID is the ID of the server group to use. + |
+
+filter+ + +ServerGroupFilter + + + |
+
+ Filter specifies a query to select an OpenStack server group. If provided, it cannot be empty. + |
+
+(Appears on: +OpenStackMachineSpec) +
++
+| Field | +Description | +
|---|---|
+key+ +string + + |
+
+ Key is the server metadata key + |
+
+value+ +string + + |
+
+ Value is the server metadata value + |
+
+(Appears on: +NetworkStatusWithSubnets) +
++
Subnet represents basic information about the associated OpenStack Neutron Subnet.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+id+ +string + + |
++ | +
+cidr+ +string + + |
++ | +
+tags+ +[]string + + |
++(Optional) + | +
+(Appears on: +SubnetParam) +
++
SubnetFilter specifies a filter to select a subnet. At least one parameter must be specified.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
++ | +
+description+ +string + + |
++ | +
+projectID+ +string + + |
++ | +
+ipVersion+ +int + + |
++ | +
+gatewayIP+ +string + + |
++ | +
+cidr+ +string + + |
++ | +
+ipv6AddressMode+ +string + + |
++ | +
+ipv6RAMode+ +string + + |
++ | +
+FilterByNeutronTags+ + +FilterByNeutronTags + + + |
+
+
+(Members of |
+
+(Appears on: +APIServerLoadBalancer, +ExternalRouterIPParam, +FixedIP, +OpenStackClusterSpec) +
++
SubnetParam specifies an OpenStack subnet to use. It may be specified by either ID or filter, but not both.
+ +| Field | +Description | +
|---|---|
+id+ +string + + |
+
+(Optional)
+ ID is the uuid of the subnet. It will not be validated. + |
+
+filter+ + +SubnetFilter + + + |
+
+(Optional)
+ Filter specifies a filter to select the subnet. It must match exactly one subnet. + |
+
+(Appears on: +OpenStackClusterSpec) +
++
+| Field | +Description | +
|---|---|
+cidr+ +string + + |
+
+ CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24. +This field is required when defining a subnet. + |
+
+dnsNameservers+ +[]string + + |
+
+ DNSNameservers holds a list of DNS server addresses that will be provided when creating +the subnet. These addresses need to have the same IP version as CIDR. + |
+
+allocationPools+ + +[]AllocationPool + + + |
+
+ AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. +If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from +outside of these ranges manually. + |
+
+(Appears on: +ResolvedPortSpecFields) +
++
ValueSpec represents a single value_spec key-value pair.
+ +| Field | +Description | +
|---|---|
+name+ +string + + |
+
+ Name is the name of the key-value pair. +This is just for identifying the pair and will not be sent to the OpenStack API. + |
+
+key+ +string + + |
+
+ Key is the key in the key-value pair. + |
+
+value+ +string + + |
+
+ Value is the value in the key-value pair. + |
+
string alias)+(Appears on: +VolumeAvailabilityZone) +
++
VolumeAZName is the name of a volume availability zone. It may not contain spaces.
+ +string alias)+(Appears on: +VolumeAvailabilityZone) +
++
VolumeAZSource specifies where to obtain the availability zone for a volume.
+ +| Value | +Description | +
|---|---|
"Machine" |
++ |
"Name" |
++ |
+(Appears on: +BlockDeviceVolume) +
++
VolumeAvailabilityZone specifies the availability zone for a volume.
+ +| Field | +Description | +
|---|---|
+from+ + +VolumeAZSource + + + |
+
+(Optional)
+ From specifies where we will obtain the availability zone for the +volume. The options are “Name” and “Machine”. If “Name” is specified +then the Name field must also be specified. If “Machine” is specified +the volume will use the value of FailureDomain, if any, from the +associated Machine. + |
+
+name+ + +VolumeAZName + + + |
+
+(Optional)
+ Name is the name of a volume availability zone to use. It is required +if From is “Name”. The volume availability zone name may not contain +spaces. + |
+
+Generated with gen-crd-api-reference-docs.
+
")
+ preCloseTag = []byte("")
+ codeTag = []byte("")
+ codeCloseTag = []byte("")
+ pTag = []byte("") + pCloseTag = []byte("
") + blockquoteTag = []byte("") + blockquoteCloseTag = []byte("") + hrTag = []byte("